Simplify FemtoVG and Skia renderer API (#3153)

Fold show() into the first time render() is invoked,
and hide() into the Drop implementation.
This commit is contained in:
Simon Hausmann 2023-07-25 17:17:40 +02:00 committed by GitHub
parent 2a56e25788
commit 507428b03e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 59 additions and 116 deletions

View file

@ -492,10 +492,6 @@ public:
{
cbindgen_private::slint_skia_renderer_resize(inner, size);
}
void hide() const { cbindgen_private::slint_skia_renderer_hide(inner); }
void show() const { cbindgen_private::slint_skia_renderer_show(inner); }
};
/// Call this function at each iteration of the event loop to call the timer handler and advance

View file

@ -451,18 +451,6 @@ pub mod skia {
drop(Box::from_raw(r as *mut SkiaRenderer))
}
#[no_mangle]
pub unsafe extern "C" fn slint_skia_renderer_show(r: SkiaRendererOpaque) {
let r = &*(r as *const SkiaRenderer);
r.show().unwrap()
}
#[no_mangle]
pub unsafe extern "C" fn slint_skia_renderer_hide(r: SkiaRendererOpaque) {
let r = &*(r as *const SkiaRenderer);
r.hide().unwrap()
}
#[no_mangle]
pub unsafe extern "C" fn slint_skia_renderer_resize(r: SkiaRendererOpaque, size: IntSize) {
let r = &*(r as *const SkiaRenderer);

View file

@ -71,16 +71,11 @@ struct MyWindowAdapter : public slint_platform::WindowAdapter
return slint::PhysicalSize({ uint32_t(r.right - r.left), uint32_t(r.bottom - r.top) });
}
void show() const override
{
ShowWindow(hwnd, SW_SHOWNORMAL);
m_renderer->show();
}
void show() const override { ShowWindow(hwnd, SW_SHOWNORMAL); }
void hide() const override
{
// TODO: destroy window
m_renderer->hide();
}
void request_redraw() const override { InvalidateRect(hwnd, nullptr, false); }

View file

@ -106,13 +106,8 @@ public:
->dispatch_scale_factor_change_event(devicePixelRatio());
auto window = const_cast<QWindow *>(static_cast<const QWindow *>(this));
window->QWindow::show();
m_renderer->show();
}
void hide() const override
{
m_renderer->hide();
const_cast<MyWindow *>(this)->QWindow::hide();
}
void hide() const override { const_cast<MyWindow *>(this)->QWindow::hide(); }
slint::PhysicalSize physical_size() const override
{
auto windowSize = slint::LogicalSize({ float(width()), float(height()) });

View file

@ -34,9 +34,6 @@ mod renderer {
where
Self: Sized;
fn show(&self) -> Result<(), PlatformError>;
fn hide(&self) -> Result<(), PlatformError>;
fn render(&self, window: &i_slint_core::api::Window) -> Result<(), PlatformError>;
fn as_core_renderer(&self) -> &dyn i_slint_core::renderer::Renderer;

View file

@ -45,14 +45,6 @@ impl super::WinitCompatibleRenderer for GlutinFemtoVGRenderer {
Ok((Self { renderer }, winit_window))
}
fn show(&self) -> Result<(), PlatformError> {
self.renderer.show()
}
fn hide(&self) -> Result<(), PlatformError> {
self.renderer.hide()
}
fn render(&self, window: &i_slint_core::api::Window) -> Result<(), PlatformError> {
self.renderer.render(window)
}

View file

@ -62,14 +62,6 @@ impl super::WinitCompatibleRenderer for SkiaRenderer {
Ok((Self { renderer }, winit_window))
}
fn show(&self) -> Result<(), PlatformError> {
self.renderer.show()
}
fn hide(&self) -> Result<(), PlatformError> {
self.renderer.hide()
}
fn render(&self, window: &i_slint_core::api::Window) -> Result<(), PlatformError> {
self.renderer.render(window)
}

View file

@ -47,14 +47,6 @@ impl super::WinitCompatibleRenderer for WinitSoftwareRenderer {
))
}
fn show(&self) -> Result<(), PlatformError> {
Ok(())
}
fn hide(&self) -> Result<(), PlatformError> {
Ok(())
}
fn render(&self, window: &i_slint_core::api::Window) -> Result<(), PlatformError> {
let size = window.size();

View file

@ -118,7 +118,6 @@ pub struct WinitWindowAdapter {
constraints: Cell<(corelib::layout::LayoutInfo, corelib::layout::LayoutInfo)>,
shown: Cell<bool>,
winit_window: Rc<winit::window::Window>,
renderer: Box<dyn WinitCompatibleRenderer>,
// We cache the size because winit_window.inner_size() can return different value between calls (eg, on X11)
// And we wan see the newer value before the Resized event was received, leading to inconsistencies
@ -129,6 +128,8 @@ pub struct WinitWindowAdapter {
#[cfg(enable_accesskit)]
pub accesskit_adapter: crate::accesskit::AccessKitAdapter,
winit_window: Rc<winit::window::Window>, // Last field so that any previously provided window handles are still valid in the drop impl of the renderers, etc.
}
impl WinitWindowAdapter {
@ -534,7 +535,6 @@ impl WindowAdapterInternal for WinitWindowAdapter {
self.size.set(physical_size_to_slint(&size));
};
self.renderer().show()?;
winit_window.set_visible(true);
// Make sure the dark color scheme property is up-to-date, as it may have been queried earlier when
@ -559,8 +559,6 @@ impl WindowAdapterInternal for WinitWindowAdapter {
fn hide(&self) -> Result<(), PlatformError> {
self.shown.set(false);
self.renderer().hide()?;
self.winit_window().set_visible(false);
/* FIXME:
@ -690,7 +688,6 @@ impl WindowAdapterInternal for WinitWindowAdapter {
impl Drop for WinitWindowAdapter {
fn drop(&mut self) {
self.renderer.hide().ok(); // ignore errors here, we're going away anyway
crate::event_loop::unregister_window(self.winit_window().id());
}
}

View file

@ -4,7 +4,7 @@
#![doc = include_str!("README.md")]
#![doc(html_logo_url = "https://slint.dev/logo/slint-logo-square-light.svg")]
use std::cell::RefCell;
use std::cell::{Cell, RefCell};
use std::pin::Pin;
use std::rc::Rc;
@ -76,6 +76,7 @@ pub struct FemtoVGRenderer {
graphics_cache: itemrenderer::ItemGraphicsCache,
texture_cache: RefCell<images::TextureCache>,
rendering_metrics_collector: RefCell<Option<Rc<RenderingMetricsCollector>>>,
rendering_first_time: Cell<bool>,
// Last field, so that it's dropped last and context exists and is current when destroying the FemtoVG canvas
opengl_context: Box<dyn OpenGLContextWrapper>,
#[cfg(target_arch = "wasm32")]
@ -139,37 +140,13 @@ impl FemtoVGRenderer {
graphics_cache: Default::default(),
texture_cache: Default::default(),
rendering_metrics_collector: Default::default(),
rendering_first_time: Cell::new(true),
opengl_context,
#[cfg(target_arch = "wasm32")]
canvas_id: html_canvas.id(),
})
}
/// Notifiers the renderer that the underlying window is becoming visible.
pub fn show(&self) -> Result<(), PlatformError> {
self.opengl_context.ensure_current()?;
*self.rendering_metrics_collector.borrow_mut() =
RenderingMetricsCollector::new("FemtoVG renderer");
if let Some(callback) = self.rendering_notifier.borrow_mut().as_mut() {
self.with_graphics_api(|api| callback.notify(RenderingState::RenderingSetup, &api))?;
}
Ok(())
}
/// Notifiers the renderer that the underlying window will be hidden soon.
pub fn hide(&self) -> Result<(), PlatformError> {
self.opengl_context.ensure_current()?;
self.rendering_metrics_collector.borrow_mut().take();
if let Some(callback) = self.rendering_notifier.borrow_mut().as_mut() {
self.with_graphics_api(|api| callback.notify(RenderingState::RenderingTeardown, &api))?;
}
Ok(())
}
/// Render the scene using OpenGL. This function assumes that the context is current.
pub fn render(
&self,
@ -177,6 +154,17 @@ impl FemtoVGRenderer {
) -> Result<(), i_slint_core::platform::PlatformError> {
self.opengl_context.ensure_current()?;
if self.rendering_first_time.take() {
*self.rendering_metrics_collector.borrow_mut() =
RenderingMetricsCollector::new("FemtoVG renderer");
if let Some(callback) = self.rendering_notifier.borrow_mut().as_mut() {
self.with_graphics_api(|api| {
callback.notify(RenderingState::RenderingSetup, &api)
})?;
}
}
let size = window.size();
let width = size.width;
let height = size.height;
@ -480,7 +468,16 @@ impl RendererSealed for FemtoVGRenderer {
impl Drop for FemtoVGRenderer {
fn drop(&mut self) {
// Ensure the context is current before the renderer is destroyed
self.opengl_context.ensure_current().ok();
if self.opengl_context.ensure_current().is_ok() {
drop(self.rendering_metrics_collector.borrow_mut().take());
if let Some(callback) = self.rendering_notifier.borrow_mut().as_mut() {
self.with_graphics_api(|api| {
callback.notify(RenderingState::RenderingTeardown, &api)
})
.ok();
}
}
// Clear these manually to drop any Rc<Canvas>.
self.graphics_cache.clear_all();

View file

@ -4,7 +4,7 @@
#![doc = include_str!("README.md")]
#![doc(html_logo_url = "https://slint.dev/logo/slint-logo-square-light.svg")]
use std::cell::RefCell;
use std::cell::{Cell, RefCell};
use std::rc::Rc;
use i_slint_core::api::{
@ -58,6 +58,7 @@ pub struct SkiaRenderer {
image_cache: ItemCache<Option<skia_safe::Image>>,
path_cache: ItemCache<Option<(Vector2D<f32, PhysicalPx>, skia_safe::Path)>>,
rendering_metrics_collector: RefCell<Option<Rc<RenderingMetricsCollector>>>,
rendering_first_time: Cell<bool>,
surface: DefaultSurface,
}
@ -75,43 +76,30 @@ impl SkiaRenderer {
image_cache: Default::default(),
path_cache: Default::default(),
rendering_metrics_collector: Default::default(),
rendering_first_time: Cell::new(true),
surface,
})
}
/// Notifiers the renderer that the underlying window is becoming visible.
pub fn show(&self) -> Result<(), PlatformError> {
*self.rendering_metrics_collector.borrow_mut() = RenderingMetricsCollector::new(&format!(
"Skia renderer (skia backend {}; surface: {} bpp)",
self.surface.name(),
self.surface.bits_per_pixel()?
));
if let Some(callback) = self.rendering_notifier.borrow_mut().as_mut() {
self.surface
.with_graphics_api(|api| callback.notify(RenderingState::RenderingSetup, &api))
}
Ok(())
}
/// Notifiers the renderer that the underlying window will be hidden soon.
pub fn hide(&self) -> Result<(), i_slint_core::platform::PlatformError> {
if let Some(callback) = self.rendering_notifier.borrow_mut().as_mut() {
self.surface.with_active_surface(|| {
self.surface.with_graphics_api(|api| {
callback.notify(RenderingState::RenderingTeardown, &api)
})
})?;
}
Ok(())
}
/// Render the scene in the previously associated window. The size parameter must match the size of the window.
pub fn render(
&self,
window: &i_slint_core::api::Window,
) -> Result<(), i_slint_core::platform::PlatformError> {
if self.rendering_first_time.take() {
*self.rendering_metrics_collector.borrow_mut() =
RenderingMetricsCollector::new(&format!(
"Skia renderer (skia backend {}; surface: {} bpp)",
self.surface.name(),
self.surface.bits_per_pixel()?
));
if let Some(callback) = self.rendering_notifier.borrow_mut().as_mut() {
self.surface
.with_graphics_api(|api| callback.notify(RenderingState::RenderingSetup, &api))
}
}
let size = window.size();
let window_inner = WindowInner::from_pub(window);
@ -347,6 +335,20 @@ impl i_slint_core::renderer::RendererSealed for SkiaRenderer {
}
}
impl Drop for SkiaRenderer {
fn drop(&mut self) {
if let Some(callback) = self.rendering_notifier.borrow_mut().as_mut() {
self.surface
.with_active_surface(|| {
self.surface.with_graphics_api(|api| {
callback.notify(RenderingState::RenderingTeardown, &api)
})
})
.ok();
}
}
}
trait Surface {
const SUPPORTS_GRAPHICS_API: bool;
fn new(