slint/internal/backends/winit/renderer/skia.rs
Simon Hausmann 93142bf417 winit: Always make skia-opengl available
The Skia OpenGL renderer is portable and sometimes esp. on Windows produces better results, so make it always available as an open if `renderer-skia` is enabled. `renderer-skia-opengl` continues to select the GL renderer as default.
2024-01-24 18:20:04 +01:00

121 lines
4.5 KiB
Rust

// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
use std::rc::Rc;
use crate::winitwindowadapter::physical_size_to_slint;
use i_slint_core::platform::PlatformError;
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
pub struct WinitSkiaRenderer {
renderer: i_slint_renderer_skia::SkiaRenderer,
}
impl WinitSkiaRenderer {
pub fn new(
window_builder: winit::window::WindowBuilder,
) -> Result<(Box<dyn super::WinitCompatibleRenderer>, Rc<winit::window::Window>), 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();
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))
}
#[cfg(not(target_os = "android"))]
pub fn new_software(
window_builder: winit::window::WindowBuilder,
) -> Result<(Box<dyn super::WinitCompatibleRenderer>, Rc<winit::window::Window>), 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_software();
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))
}
pub fn new_opengl(
window_builder: winit::window::WindowBuilder,
) -> Result<(Box<dyn super::WinitCompatibleRenderer>, Rc<winit::window::Window>), 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 {
fn render(&self, _window: &i_slint_core::api::Window) -> Result<(), PlatformError> {
self.renderer.render()
}
fn as_core_renderer(&self) -> &dyn i_slint_core::renderer::Renderer {
&self.renderer
}
fn resumed(&self, winit_window: &winit::window::Window) -> Result<(), PlatformError> {
let size = winit_window.inner_size();
// Safety: This is safe because the handle remains valid; the next rwh release provides `new()` without unsafe.
let active_handle = unsafe { raw_window_handle::ActiveHandle::new_unchecked() };
// Safety: API wise we can't guarantee that the window/display handles remain valid, so we
// use unsafe here. However the winit window adapter keeps the winit window alive as long as
// the renderer.
// TODO: remove once winit implements HasWindowHandle/HasDisplayHandle
let (window_handle, display_handle) = unsafe {
(
raw_window_handle::WindowHandle::borrow_raw(
winit_window.raw_window_handle(),
active_handle,
),
raw_window_handle::DisplayHandle::borrow_raw(winit_window.raw_display_handle()),
)
};
self.renderer.set_window_handle(
window_handle,
display_handle,
physical_size_to_slint(&size),
)
}
}