mirror of
https://github.com/slint-ui/slint.git
synced 2025-11-03 13:23:00 +00:00
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:
parent
40f2833bac
commit
4c888bf1ae
10 changed files with 156 additions and 123 deletions
|
|
@ -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(),
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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) });
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue