diff --git a/docs/reference/src/advanced/backend_winit.md b/docs/reference/src/advanced/backend_winit.md index d123e3fd8..394113742 100644 --- a/docs/reference/src/advanced/backend_winit.md +++ b/docs/reference/src/advanced/backend_winit.md @@ -15,6 +15,7 @@ The Winit backend supports different renderers. They can be explicitly selected | FemtoVG | OpenGL | `winit-femtovg` | | Skia | OpenGL, Metal, Direct3D, Software-rendering | `winit-skia` | | Skia Software | Software-only rendering with Skia | `winit-skia-software` | +| Skia OpenGL | OpenGL rendering with Skia | `winit-skia-opengl` | | software | Software-rendering, no GPU required | `winit-software` | diff --git a/internal/backends/winit/lib.rs b/internal/backends/winit/lib.rs index f39c7e99e..7e1234a51 100644 --- a/internal/backends/winit/lib.rs +++ b/internal/backends/winit/lib.rs @@ -177,6 +177,8 @@ impl Backend { Some("gl") | Some("femtovg") => renderer::femtovg::GlutinFemtoVGRenderer::new, #[cfg(enable_skia_renderer)] Some("skia") => renderer::skia::WinitSkiaRenderer::new, + #[cfg(enable_skia_renderer)] + Some("skia-opengl") => renderer::skia::WinitSkiaRenderer::new_opengl, #[cfg(all(enable_skia_renderer, not(target_os = "android")))] Some("skia-software") => renderer::skia::WinitSkiaRenderer::new_software, #[cfg(feature = "renderer-software")] diff --git a/internal/backends/winit/renderer/skia.rs b/internal/backends/winit/renderer/skia.rs index 2e1fcdb23..2f98d3035 100644 --- a/internal/backends/winit/renderer/skia.rs +++ b/internal/backends/winit/renderer/skia.rs @@ -58,6 +58,29 @@ impl WinitSkiaRenderer { Ok((Box::new(Self { renderer }), winit_window)) } + + pub fn new_opengl( + window_builder: winit::window::WindowBuilder, + ) -> Result<(Box, Rc), PlatformError> + { + let winit_window = Rc::new(crate::event_loop::with_window_target(|event_loop| { + window_builder.build(event_loop.event_loop_target()).map_err(|winit_os_error| { + format!("Error creating native window for Skia rendering: {}", winit_os_error) + .into() + }) + })?); + + let renderer = i_slint_renderer_skia::SkiaRenderer::default_opengl(); + + renderer.set_pre_present_callback(Some(Box::new({ + let winit_window = winit_window.clone(); + move || { + winit_window.pre_present_notify(); + } + }))); + + Ok((Box::new(Self { renderer }), winit_window)) + } } impl super::WinitCompatibleRenderer for WinitSkiaRenderer { diff --git a/internal/renderers/skia/Cargo.toml b/internal/renderers/skia/Cargo.toml index 874125632..34247b084 100644 --- a/internal/renderers/skia/Cargo.toml +++ b/internal/renderers/skia/Cargo.toml @@ -21,7 +21,7 @@ path = "lib.rs" [features] wayland = ["glutin/wayland", "softbuffer/wayland", "softbuffer/wayland-dlopen"] x11 = ["glutin/x11", "glutin/glx", "softbuffer/x11", "softbuffer/x11-dlopen"] -opengl = ["skia-safe/gl"] +opengl = [] vulkan = ["skia-safe/vulkan", "ash", "vulkano"] kms = ["softbuffer/kms"] default = [] @@ -42,7 +42,7 @@ pin-weak = "1" scoped-tls-hkt = "0.1" raw-window-handle = { version = "0.5", features = ["std"] } -skia-safe = { version = "0.69.0", features = ["textlayout"] } +skia-safe = { version = "0.69.0", features = ["textlayout", "gl"] } glow = { version = "0.13" } unicode-segmentation = { version = "1.8.0" } diff --git a/internal/renderers/skia/lib.rs b/internal/renderers/skia/lib.rs index 851f2e5a8..3b197474c 100644 --- a/internal/renderers/skia/lib.rs +++ b/internal/renderers/skia/lib.rs @@ -43,7 +43,6 @@ pub mod d3d_surface; #[cfg(skia_backend_vulkan)] pub mod vulkan_surface; -#[cfg(skia_backend_opengl)] pub mod opengl_surface; pub use skia_safe; @@ -135,6 +134,24 @@ impl SkiaRenderer { } } + /// Creates a new SkiaRenderer that will always use Skia's OpenGL renderer. + pub fn default_opengl() -> Self { + Self { + maybe_window_adapter: Default::default(), + rendering_notifier: Default::default(), + image_cache: Default::default(), + path_cache: Default::default(), + rendering_metrics_collector: Default::default(), + rendering_first_time: Default::default(), + surface: Default::default(), + surface_factory: |window_handle, display_handle, size| { + opengl_surface::OpenGLSurface::new(window_handle, display_handle, size) + .map(|r| Box::new(r) as Box) + }, + pre_present_callback: Default::default(), + } + } + /// Creates a new renderer is associated with the provided window adapter. pub fn new( window_handle: raw_window_handle::WindowHandle<'_>,