Port the Skia renderer to rwh06 and the new softbuffer

... by accepting an Rc<dyn Has*Handle> in the interface. This is required for softbuffer use.
This commit is contained in:
Simon Hausmann 2024-06-17 17:46:09 +02:00
parent 40f2833bac
commit 4c888bf1ae
10 changed files with 156 additions and 123 deletions

View file

@ -511,18 +511,34 @@ mod software_renderer {
pub mod skia { pub mod skia {
use super::*; use super::*;
use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
use std::rc::Rc;
struct CppRawHandle(RawWindowHandle, RawDisplayHandle); struct RawHandlePair((RawWindowHandle, RawDisplayHandle));
// the raw handle type are #[non_exhaustive], so they can't be initialize with the convenient syntax. Work that around. impl raw_window_handle::HasDisplayHandle for RawHandlePair {
macro_rules! init_raw { fn display_handle(
($ty:ty { $($var:ident),* }) => { &self,
{ ) -> Result<raw_window_handle::DisplayHandle<'_>, raw_window_handle::HandleError> {
let mut h = <$ty>::empty(); // Safety: It is assumed that the C++ side keeps the window/display handles alive.
$(h.$var = $var;)* Ok(unsafe { raw_window_handle::DisplayHandle::borrow_raw(self.0 .1) })
h }
} }
};
impl raw_window_handle::HasWindowHandle for RawHandlePair {
fn window_handle(
&self,
) -> Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
// Safety: It is assumed that the C++ side keeps the window/display handles alive.
Ok(unsafe { raw_window_handle::WindowHandle::borrow_raw(self.0 .0) })
}
}
struct CppRawHandle(Rc<RawHandlePair>);
impl From<(RawWindowHandle, RawDisplayHandle)> for CppRawHandle {
fn from(pair: (RawWindowHandle, RawDisplayHandle)) -> Self {
Self(Rc::new(RawHandlePair(pair)))
}
} }
type CppRawHandleOpaque = *const c_void; type CppRawHandleOpaque = *const c_void;
@ -530,15 +546,14 @@ pub mod skia {
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn slint_new_raw_window_handle_win32( pub unsafe extern "C" fn slint_new_raw_window_handle_win32(
hwnd: *mut c_void, hwnd: *mut c_void,
hinstance: *mut c_void, _hinstance: *mut c_void,
) -> CppRawHandleOpaque { ) -> CppRawHandleOpaque {
let handle = CppRawHandle( let handle = CppRawHandle::from((
RawWindowHandle::Win32(init_raw!(raw_window_handle::Win32WindowHandle { RawWindowHandle::Win32(raw_window_handle::Win32WindowHandle::new(
hwnd, (hwnd as isize).try_into().expect("C++: NativeWindowHandle created with null hwnd"),
hinstance )),
})), RawDisplayHandle::Windows(raw_window_handle::WindowsDisplayHandle::new()),
RawDisplayHandle::Windows(raw_window_handle::WindowsDisplayHandle::empty()), ));
);
Box::into_raw(Box::new(handle)) as CppRawHandleOpaque Box::into_raw(Box::new(handle)) as CppRawHandleOpaque
} }
@ -550,10 +565,21 @@ pub mod skia {
screen: core::ffi::c_int, screen: core::ffi::c_int,
) -> CppRawHandleOpaque { ) -> CppRawHandleOpaque {
use raw_window_handle::{XcbDisplayHandle, XcbWindowHandle}; use raw_window_handle::{XcbDisplayHandle, XcbWindowHandle};
let handle = CppRawHandle( let handle = CppRawHandle::from((
RawWindowHandle::Xcb(init_raw!(XcbWindowHandle { window, visual_id })), RawWindowHandle::Xcb({
RawDisplayHandle::Xcb(init_raw!(XcbDisplayHandle { connection, screen })), let mut hnd = XcbWindowHandle::new(
); window
.try_into()
.expect("C++: NativeWindowHandle created with null xcb window handle"),
);
hnd.visual_id = visual_id.try_into().ok();
hnd
}),
RawDisplayHandle::Xcb(XcbDisplayHandle::new(
Some(core::ptr::NonNull::new_unchecked(connection)),
screen,
)),
));
Box::into_raw(Box::new(handle)) as CppRawHandleOpaque Box::into_raw(Box::new(handle)) as CppRawHandleOpaque
} }
@ -565,10 +591,17 @@ pub mod skia {
screen: core::ffi::c_int, screen: core::ffi::c_int,
) -> CppRawHandleOpaque { ) -> CppRawHandleOpaque {
use raw_window_handle::{XlibDisplayHandle, XlibWindowHandle}; use raw_window_handle::{XlibDisplayHandle, XlibWindowHandle};
let handle = CppRawHandle( let handle = CppRawHandle::from((
RawWindowHandle::Xlib(init_raw!(XlibWindowHandle { window, visual_id })), RawWindowHandle::Xlib({
RawDisplayHandle::Xlib(init_raw!(XlibDisplayHandle { display, screen })), let mut hnd = XlibWindowHandle::new(window);
); hnd.visual_id = visual_id;
hnd
}),
RawDisplayHandle::Xlib(XlibDisplayHandle::new(
Some(core::ptr::NonNull::new_unchecked(display)),
screen,
)),
));
Box::into_raw(Box::new(handle)) as CppRawHandleOpaque Box::into_raw(Box::new(handle)) as CppRawHandleOpaque
} }
@ -578,23 +611,29 @@ pub mod skia {
display: *mut c_void, display: *mut c_void,
) -> CppRawHandleOpaque { ) -> CppRawHandleOpaque {
use raw_window_handle::{WaylandDisplayHandle, WaylandWindowHandle}; use raw_window_handle::{WaylandDisplayHandle, WaylandWindowHandle};
let handle = CppRawHandle( let handle = CppRawHandle::from((
RawWindowHandle::Wayland(init_raw!(WaylandWindowHandle { surface })), RawWindowHandle::Wayland(WaylandWindowHandle::new(core::ptr::NonNull::new_unchecked(
RawDisplayHandle::Wayland(init_raw!(WaylandDisplayHandle { display })), surface,
); ))),
RawDisplayHandle::Wayland(WaylandDisplayHandle::new(
core::ptr::NonNull::new_unchecked(display),
)),
));
Box::into_raw(Box::new(handle)) as CppRawHandleOpaque Box::into_raw(Box::new(handle)) as CppRawHandleOpaque
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn slint_new_raw_window_handle_appkit( pub unsafe extern "C" fn slint_new_raw_window_handle_appkit(
ns_view: *mut c_void, ns_view: *mut c_void,
ns_window: *mut c_void, _ns_window: *mut c_void,
) -> CppRawHandleOpaque { ) -> CppRawHandleOpaque {
use raw_window_handle::{AppKitDisplayHandle, AppKitWindowHandle}; use raw_window_handle::{AppKitDisplayHandle, AppKitWindowHandle};
let handle = CppRawHandle( let handle = CppRawHandle::from((
RawWindowHandle::AppKit(init_raw!(AppKitWindowHandle { ns_view, ns_window })), RawWindowHandle::AppKit(AppKitWindowHandle::new(core::ptr::NonNull::new_unchecked(
RawDisplayHandle::AppKit(AppKitDisplayHandle::empty()), ns_view,
); ))),
RawDisplayHandle::AppKit(AppKitDisplayHandle::new()),
));
Box::into_raw(Box::new(handle)) as CppRawHandleOpaque Box::into_raw(Box::new(handle)) as CppRawHandleOpaque
} }
@ -613,21 +652,10 @@ pub mod skia {
) -> SkiaRendererOpaque { ) -> SkiaRendererOpaque {
let handle = &*(handle_opaque as *const CppRawHandle); let handle = &*(handle_opaque as *const CppRawHandle);
// 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: the C++ code should ensure that the handle is valid
let (window_handle, display_handle) = unsafe {
(
raw_window_handle::WindowHandle::borrow_raw(handle.0, active_handle),
raw_window_handle::DisplayHandle::borrow_raw(handle.1),
)
};
let boxed_renderer: Box<SkiaRenderer> = Box::new( let boxed_renderer: Box<SkiaRenderer> = Box::new(
SkiaRenderer::new( SkiaRenderer::new(
window_handle, handle.0.clone(),
display_handle, handle.0.clone(),
PhysicalSize { width: size.width, height: size.height }, PhysicalSize { width: size.width, height: size.height },
) )
.unwrap(), .unwrap(),

View file

@ -485,7 +485,7 @@ impl EventLoopState {
Event::Resumed => ALL_WINDOWS.with(|ws| { Event::Resumed => ALL_WINDOWS.with(|ws| {
for (_, window_weak) in ws.borrow().iter() { for (_, window_weak) in ws.borrow().iter() {
if let Some(w) = window_weak.upgrade() { if let Some(w) = window_weak.upgrade() {
if let Err(e) = w.renderer.resumed(&w.winit_window()) { if let Err(e) = w.renderer.resumed(w.winit_window()) {
self.loop_error = Some(e); self.loop_error = Some(e);
} }
} }

View file

@ -32,6 +32,8 @@ pub enum SlintUserEvent {
} }
mod renderer { mod renderer {
use std::rc::Rc;
use i_slint_core::platform::PlatformError; use i_slint_core::platform::PlatformError;
pub trait WinitCompatibleRenderer { pub trait WinitCompatibleRenderer {
@ -43,7 +45,7 @@ mod renderer {
fn occluded(&self, _: bool) {} fn occluded(&self, _: bool) {}
// Got winit::Event::Resumed // Got winit::Event::Resumed
fn resumed(&self, _winit_window: &winit::window::Window) -> Result<(), PlatformError> { fn resumed(&self, _winit_window: Rc<winit::window::Window>) -> Result<(), PlatformError> {
Ok(()) Ok(())
} }
} }

View file

@ -5,7 +5,6 @@ use std::rc::Rc;
use crate::winitwindowadapter::physical_size_to_slint; use crate::winitwindowadapter::physical_size_to_slint;
use i_slint_core::platform::PlatformError; use i_slint_core::platform::PlatformError;
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
pub struct WinitSkiaRenderer { pub struct WinitSkiaRenderer {
renderer: i_slint_renderer_skia::SkiaRenderer, renderer: i_slint_renderer_skia::SkiaRenderer,
@ -13,11 +12,11 @@ pub struct WinitSkiaRenderer {
impl WinitSkiaRenderer { impl WinitSkiaRenderer {
pub fn new( pub fn new(
window_builder: winit::window::WindowBuilder, window_attributes: winit::window::WindowAttributes,
) -> Result<(Box<dyn super::WinitCompatibleRenderer>, Rc<winit::window::Window>), PlatformError> ) -> Result<(Box<dyn super::WinitCompatibleRenderer>, Rc<winit::window::Window>), PlatformError>
{ {
let winit_window = Rc::new(crate::event_loop::with_window_target(|event_loop| { 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| { event_loop.create_window(window_attributes).map_err(|winit_os_error| {
format!("Error creating native window for Skia rendering: {}", winit_os_error) format!("Error creating native window for Skia rendering: {}", winit_os_error)
.into() .into()
}) })
@ -37,11 +36,11 @@ impl WinitSkiaRenderer {
#[cfg(not(target_os = "android"))] #[cfg(not(target_os = "android"))]
pub fn new_software( pub fn new_software(
window_builder: winit::window::WindowBuilder, window_attributes: winit::window::WindowAttributes,
) -> Result<(Box<dyn super::WinitCompatibleRenderer>, Rc<winit::window::Window>), PlatformError> ) -> Result<(Box<dyn super::WinitCompatibleRenderer>, Rc<winit::window::Window>), PlatformError>
{ {
let winit_window = Rc::new(crate::event_loop::with_window_target(|event_loop| { 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| { event_loop.create_window(window_attributes).map_err(|winit_os_error| {
format!("Error creating native window for Skia rendering: {}", winit_os_error) format!("Error creating native window for Skia rendering: {}", winit_os_error)
.into() .into()
}) })
@ -60,11 +59,11 @@ impl WinitSkiaRenderer {
} }
pub fn new_opengl( pub fn new_opengl(
window_builder: winit::window::WindowBuilder, window_attributes: winit::window::WindowAttributes,
) -> Result<(Box<dyn super::WinitCompatibleRenderer>, Rc<winit::window::Window>), PlatformError> ) -> Result<(Box<dyn super::WinitCompatibleRenderer>, Rc<winit::window::Window>), PlatformError>
{ {
let winit_window = Rc::new(crate::event_loop::with_window_target(|event_loop| { 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| { event_loop.create_window(window_attributes).map_err(|winit_os_error| {
format!("Error creating native window for Skia rendering: {}", winit_os_error) format!("Error creating native window for Skia rendering: {}", winit_os_error)
.into() .into()
}) })
@ -92,29 +91,12 @@ impl super::WinitCompatibleRenderer for WinitSkiaRenderer {
&self.renderer &self.renderer
} }
fn resumed(&self, winit_window: &winit::window::Window) -> Result<(), PlatformError> { fn resumed(&self, winit_window: Rc<winit::window::Window>) -> Result<(), PlatformError> {
let size = winit_window.inner_size(); 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( self.renderer.set_window_handle(
window_handle, winit_window.clone(),
display_handle, winit_window.clone(),
physical_size_to_slint(&size), physical_size_to_slint(&size),
winit_window.scale_factor() as f32, winit_window.scale_factor() as f32,
) )

View file

@ -174,7 +174,7 @@ impl WinitWindowAdapter {
}); });
let winit_window = self_rc.winit_window(); let winit_window = self_rc.winit_window();
if let Err(e) = self_rc.renderer.resumed(&winit_window) { if let Err(e) = self_rc.renderer.resumed(winit_window.clone()) {
i_slint_core::debug_log!("Error initialing renderer in winit backend with window: {e}"); i_slint_core::debug_log!("Error initialing renderer in winit backend with window: {e}");
} }
let id = winit_window.id(); let id = winit_window.id();

View file

@ -4,6 +4,7 @@
use i_slint_core::api::PhysicalSize as PhysicalWindowSize; use i_slint_core::api::PhysicalSize as PhysicalWindowSize;
use i_slint_core::platform::PlatformError; use i_slint_core::platform::PlatformError;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc;
use windows::core::Interface; use windows::core::Interface;
use windows::Win32::Graphics::Direct3D::D3D_FEATURE_LEVEL_11_0; use windows::Win32::Graphics::Direct3D::D3D_FEATURE_LEVEL_11_0;
use windows::Win32::Graphics::Dxgi::Common::DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN; use windows::Win32::Graphics::Dxgi::Common::DXGI_STANDARD_MULTISAMPLE_QUALITY_PATTERN;
@ -245,8 +246,8 @@ pub struct D3DSurface {
impl super::Surface for D3DSurface { impl super::Surface for D3DSurface {
fn new( fn new(
window_handle: raw_window_handle::WindowHandle<'_>, window_handle: Rc<dyn raw_window_handle::HasWindowHandle>,
_display_handle: raw_window_handle::DisplayHandle<'_>, _display_handle: Rc<dyn raw_window_handle::HasDisplayHandle>,
size: PhysicalWindowSize, size: PhysicalWindowSize,
) -> Result<Self, i_slint_core::platform::PlatformError> { ) -> Result<Self, i_slint_core::platform::PlatformError> {
let factory_flags = 0; let factory_flags = 0;
@ -357,6 +358,10 @@ impl super::Surface for D3DSurface {
let gr_context = unsafe { skia_safe::gpu::DirectContext::new_d3d(&backend_context, None) } let gr_context = unsafe { skia_safe::gpu::DirectContext::new_d3d(&backend_context, None) }
.ok_or_else(|| format!("unable to create Skia D3D DirectContext"))?; .ok_or_else(|| format!("unable to create Skia D3D DirectContext"))?;
let window_handle = window_handle
.window_handle()
.map_err(|e| format!("error obtaining window handle for skia d3d renderer: {e}"))?;
let swap_chain = RefCell::new(SwapChain::new( let swap_chain = RefCell::new(SwapChain::new(
queue, queue,
&device, &device,

View file

@ -63,8 +63,8 @@ cfg_if::cfg_if! {
} }
fn create_default_surface( fn create_default_surface(
window_handle: raw_window_handle::WindowHandle<'_>, window_handle: Rc<dyn raw_window_handle::HasWindowHandle>,
display_handle: raw_window_handle::DisplayHandle<'_>, display_handle: Rc<dyn raw_window_handle::HasDisplayHandle>,
size: PhysicalWindowSize, size: PhysicalWindowSize,
) -> Result<Box<dyn Surface>, PlatformError> { ) -> Result<Box<dyn Surface>, PlatformError> {
match DefaultSurface::new(window_handle.clone(), display_handle.clone(), size) { match DefaultSurface::new(window_handle.clone(), display_handle.clone(), size) {
@ -94,8 +94,8 @@ pub struct SkiaRenderer {
rendering_first_time: Cell<bool>, rendering_first_time: Cell<bool>,
surface: RefCell<Option<Box<dyn Surface>>>, surface: RefCell<Option<Box<dyn Surface>>>,
surface_factory: fn( surface_factory: fn(
window_handle: raw_window_handle::WindowHandle<'_>, window_handle: Rc<dyn raw_window_handle::HasWindowHandle>,
display_handle: raw_window_handle::DisplayHandle<'_>, display_handle: Rc<dyn raw_window_handle::HasDisplayHandle>,
size: PhysicalWindowSize, size: PhysicalWindowSize,
) -> Result<Box<dyn Surface>, PlatformError>, ) -> Result<Box<dyn Surface>, PlatformError>,
pre_present_callback: RefCell<Option<Box<dyn FnMut()>>>, pre_present_callback: RefCell<Option<Box<dyn FnMut()>>>,
@ -157,8 +157,8 @@ impl SkiaRenderer {
/// Creates a new renderer is associated with the provided window adapter. /// Creates a new renderer is associated with the provided window adapter.
pub fn new( pub fn new(
window_handle: raw_window_handle::WindowHandle<'_>, window_handle: Rc<dyn raw_window_handle::HasWindowHandle>,
display_handle: raw_window_handle::DisplayHandle<'_>, display_handle: Rc<dyn raw_window_handle::HasDisplayHandle>,
size: PhysicalWindowSize, size: PhysicalWindowSize,
) -> Result<Self, PlatformError> { ) -> Result<Self, PlatformError> {
Ok(Self::new_with_surface(create_default_surface(window_handle, display_handle, size)?)) Ok(Self::new_with_surface(create_default_surface(window_handle, display_handle, size)?))
@ -192,8 +192,8 @@ impl SkiaRenderer {
/// Reset the surface to the window given the window handle /// Reset the surface to the window given the window handle
pub fn set_window_handle( pub fn set_window_handle(
&self, &self,
window_handle: raw_window_handle::WindowHandle<'_>, window_handle: Rc<dyn raw_window_handle::HasWindowHandle>,
display_handle: raw_window_handle::DisplayHandle<'_>, display_handle: Rc<dyn raw_window_handle::HasDisplayHandle>,
size: PhysicalWindowSize, size: PhysicalWindowSize,
scale_factor: f32, scale_factor: f32,
) -> Result<(), PlatformError> { ) -> Result<(), PlatformError> {
@ -547,8 +547,8 @@ impl Drop for SkiaRenderer {
pub trait Surface { pub trait Surface {
/// Creates a new surface with the given window, display, and size. /// Creates a new surface with the given window, display, and size.
fn new( fn new(
window_handle: raw_window_handle::WindowHandle<'_>, window_handle: Rc<dyn raw_window_handle::HasWindowHandle>,
display_handle: raw_window_handle::DisplayHandle<'_>, display_handle: Rc<dyn raw_window_handle::HasDisplayHandle>,
size: PhysicalWindowSize, size: PhysicalWindowSize,
) -> Result<Self, PlatformError> ) -> Result<Self, PlatformError>
where where

View file

@ -8,10 +8,10 @@ use i_slint_core::api::PhysicalSize as PhysicalWindowSize;
use metal::MTLPixelFormat; use metal::MTLPixelFormat;
use objc::{rc::autoreleasepool, runtime::YES}; use objc::{rc::autoreleasepool, runtime::YES};
use raw_window_handle::HasRawWindowHandle;
use skia_safe::gpu::mtl; use skia_safe::gpu::mtl;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc;
/// This surface renders into the given window using Metal. The provided display argument /// This surface renders into the given window using Metal. The provided display argument
/// is ignored, as it has no meaning on macOS. /// is ignored, as it has no meaning on macOS.
@ -23,8 +23,8 @@ pub struct MetalSurface {
impl super::Surface for MetalSurface { impl super::Surface for MetalSurface {
fn new( fn new(
window_handle: raw_window_handle::WindowHandle<'_>, window_handle: Rc<dyn raw_window_handle::HasWindowHandle>,
_display_handle: raw_window_handle::DisplayHandle<'_>, _display_handle: Rc<dyn raw_window_handle::HasDisplayHandle>,
size: PhysicalWindowSize, size: PhysicalWindowSize,
) -> Result<Self, i_slint_core::platform::PlatformError> { ) -> Result<Self, i_slint_core::platform::PlatformError> {
let device = metal::Device::system_default() let device = metal::Device::system_default()
@ -39,10 +39,14 @@ impl super::Surface for MetalSurface {
layer.set_drawable_size(CGSize::new(size.width as f64, size.height as f64)); layer.set_drawable_size(CGSize::new(size.width as f64, size.height as f64));
unsafe { unsafe {
let view = match window_handle.raw_window_handle() { let view = match window_handle
.window_handle()
.map_err(|e| format!("Error obtaining window handle for skia metal renderer: {e}"))?
.as_raw()
{
raw_window_handle::RawWindowHandle::AppKit( raw_window_handle::RawWindowHandle::AppKit(
raw_window_handle::AppKitWindowHandle { ns_view, .. }, raw_window_handle::AppKitWindowHandle { ns_view, .. },
) => ns_view, ) => ns_view.as_ptr(),
_ => { _ => {
return Err("Skia Renderer: Metal surface is only supported with AppKit".into()) return Err("Skia Renderer: Metal surface is only supported with AppKit".into())
} }

View file

@ -1,7 +1,9 @@
// Copyright © SixtyFPS GmbH <info@slint.dev> // Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
use std::{cell::RefCell, num::NonZeroU32}; use std::cell::RefCell;
use std::num::NonZeroU32;
use std::rc::Rc;
use glutin::{ use glutin::{
config::GetGlConfig, config::GetGlConfig,
@ -24,8 +26,8 @@ pub struct OpenGLSurface {
impl super::Surface for OpenGLSurface { impl super::Surface for OpenGLSurface {
fn new( fn new(
window_handle: raw_window_handle::WindowHandle<'_>, window_handle: Rc<dyn raw_window_handle::HasWindowHandle>,
display_handle: raw_window_handle::DisplayHandle<'_>, display_handle: Rc<dyn raw_window_handle::HasDisplayHandle>,
size: PhysicalWindowSize, size: PhysicalWindowSize,
) -> Result<Self, PlatformError> { ) -> Result<Self, PlatformError> {
let width: std::num::NonZeroU32 = size.width.try_into().map_err(|_| { let width: std::num::NonZeroU32 = size.width.try_into().map_err(|_| {
@ -35,6 +37,13 @@ impl super::Surface for OpenGLSurface {
format!("Attempting to create window surface with an invalid height: {}", size.height) format!("Attempting to create window surface with an invalid height: {}", size.height)
})?; })?;
let window_handle = window_handle
.window_handle()
.map_err(|e| format!("error obtaining window handle for skia opengl renderer: {e}"))?;
let display_handle = display_handle
.display_handle()
.map_err(|e| format!("error obtaining display handle for skia opengl renderer: {e}"))?;
let (current_glutin_context, glutin_surface) = let (current_glutin_context, glutin_surface) =
Self::init_glutin(window_handle, display_handle, width, height)?; Self::init_glutin(window_handle, display_handle, width, height)?;
@ -220,17 +229,14 @@ impl OpenGLSurface {
} }
let gl_display = unsafe { let gl_display = unsafe {
glutin::display::Display::new( glutin::display::Display::new(_display_handle.as_raw(), display_api_preference)
_display_handle.as_raw(), .map_err(|glutin_error| {
display_api_preference, format!(
) "Error creating glutin display for native display {:#?}: {}",
.map_err(|glutin_error| { _display_handle.as_raw(),
format!( glutin_error
"Error creating glutin display for native display {:#?}: {}", )
_display_handle.as_raw(), })?
glutin_error
)
})?
}; };
let config_template_builder = glutin::config::ConfigTemplateBuilder::new(); let config_template_builder = glutin::config::ConfigTemplateBuilder::new();
@ -315,10 +321,10 @@ impl OpenGLSurface {
if let raw_window_handle::RawWindowHandle::AppKit(raw_window_handle::AppKitWindowHandle { if let raw_window_handle::RawWindowHandle::AppKit(raw_window_handle::AppKitWindowHandle {
ns_view, ns_view,
.. ..
}) = _window_handle.raw_window_handle() }) = _window_handle.as_raw()
{ {
use cocoa::appkit::NSView; use cocoa::appkit::NSView;
let view_id: cocoa::base::id = ns_view as *const _ as *mut _; let view_id: cocoa::base::id = ns_view.as_ptr() as *const _ as *mut _;
unsafe { unsafe {
NSView::setLayerContentsPlacement(view_id, cocoa::appkit::NSViewLayerContentsPlacement::NSViewLayerContentsPlacementTopLeft) NSView::setLayerContentsPlacement(view_id, cocoa::appkit::NSViewLayerContentsPlacement::NSViewLayerContentsPlacementTopLeft)
} }

View file

@ -3,7 +3,9 @@
use i_slint_core::api::PhysicalSize as PhysicalWindowSize; use i_slint_core::api::PhysicalSize as PhysicalWindowSize;
use std::{cell::RefCell, num::NonZeroU32}; use std::cell::RefCell;
use std::num::NonZeroU32;
use std::rc::Rc;
pub trait RenderBuffer { pub trait RenderBuffer {
fn with_buffer( fn with_buffer(
@ -20,8 +22,13 @@ pub trait RenderBuffer {
} }
struct SoftbufferRenderBuffer { struct SoftbufferRenderBuffer {
_context: softbuffer::Context, _context: softbuffer::Context<Rc<dyn raw_window_handle::HasDisplayHandle>>,
surface: RefCell<softbuffer::Surface>, surface: RefCell<
softbuffer::Surface<
Rc<dyn raw_window_handle::HasDisplayHandle>,
Rc<dyn raw_window_handle::HasWindowHandle>,
>,
>,
} }
impl RenderBuffer for SoftbufferRenderBuffer { impl RenderBuffer for SoftbufferRenderBuffer {
@ -74,18 +81,17 @@ pub struct SoftwareSurface {
impl super::Surface for SoftwareSurface { impl super::Surface for SoftwareSurface {
fn new( fn new(
window_handle: raw_window_handle::WindowHandle<'_>, window_handle: Rc<dyn raw_window_handle::HasWindowHandle>,
display_handle: raw_window_handle::DisplayHandle<'_>, display_handle: Rc<dyn raw_window_handle::HasDisplayHandle>,
_size: PhysicalWindowSize, _size: PhysicalWindowSize,
) -> Result<Self, i_slint_core::platform::PlatformError> { ) -> Result<Self, i_slint_core::platform::PlatformError> {
let _context = unsafe { let _context = softbuffer::Context::new(display_handle)
softbuffer::Context::new(&display_handle) .map_err(|e| format!("Error creating softbuffer context: {e}"))?;
.map_err(|e| format!("Error creating softbuffer context: {e}"))?
};
let surface = unsafe { softbuffer::Surface::new(&_context, &window_handle) }.map_err( let surface =
|softbuffer_error| format!("Error creating softbuffer surface: {}", softbuffer_error), softbuffer::Surface::new(&_context, window_handle).map_err(|softbuffer_error| {
)?; format!("Error creating softbuffer surface: {}", softbuffer_error)
})?;
let surface_access = let surface_access =
Box::new(SoftbufferRenderBuffer { _context, surface: RefCell::new(surface) }); Box::new(SoftbufferRenderBuffer { _context, surface: RefCell::new(surface) });