Skip to content

Commit

Permalink
Simplify FemtoVG renderer API
Browse files Browse the repository at this point in the history
For wasm builds, just require the canvas element.
  • Loading branch information
tronical committed Jun 7, 2023
1 parent 2b891b6 commit af6b49a
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 40 deletions.
13 changes: 13 additions & 0 deletions internal/backends/winit/renderer/femtovg.rs
Expand Up @@ -9,6 +9,7 @@ use i_slint_renderer_femtovg::FemtoVGRenderer;
#[cfg(target_arch = "wasm32")]
use winit::platform::web::WindowExtWebSys;

#[cfg(not(target_arch = "wasm32"))]
mod glcontext;

pub struct GlutinFemtoVGRenderer {
Expand All @@ -19,11 +20,23 @@ impl super::WinitCompatibleRenderer for GlutinFemtoVGRenderer {
fn new(
window_builder: winit::window::WindowBuilder,
) -> Result<(Self, winit::window::Window), PlatformError> {
#[cfg(not(target_arch = "wasm32"))]
let (winit_window, opengl_context) = crate::event_loop::with_window_target(|event_loop| {
glcontext::OpenGLContext::new_context(window_builder, event_loop.event_loop_target())
})?;

#[cfg(target_arch = "wasm32")]
let winit_window = crate::event_loop::with_window_target(|event_loop| {
window_builder.build(event_loop.event_loop_target()).map_err(|winit_os_err| {
format!(
"FemtoVG Renderer: Could not create winit window wrapper for DOM canvas: {}",
winit_os_err
)
})
})?;

let renderer = FemtoVGRenderer::new(
#[cfg(not(target_arch = "wasm32"))]
opengl_context,
#[cfg(target_arch = "wasm32")]
winit_window.canvas(),
Expand Down
48 changes: 9 additions & 39 deletions internal/backends/winit/renderer/femtovg/glcontext.rs
@@ -1,27 +1,22 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial

#[cfg(not(target_arch = "wasm32"))]
use glutin::{
context::{ContextApi, ContextAttributesBuilder},
display::GetGlDisplay,
prelude::*,
surface::{SurfaceAttributesBuilder, WindowSurface},
};
use i_slint_core::{api::PhysicalSize, platform::PlatformError};
#[cfg(not(target_arch = "wasm32"))]
use raw_window_handle::HasRawWindowHandle;

pub struct OpenGLContext {
#[cfg(not(target_arch = "wasm32"))]
context: glutin::context::PossiblyCurrentContext,
#[cfg(not(target_arch = "wasm32"))]
surface: glutin::surface::Surface<glutin::surface::WindowSurface>,
}

unsafe impl i_slint_renderer_femtovg::OpenGLContextWrapper for OpenGLContext {
fn ensure_current(&self) -> Result<(), PlatformError> {
#[cfg(not(target_arch = "wasm32"))]
if !self.context.is_current() {
self.context.make_current(&self.surface).map_err(|glutin_error| -> PlatformError {
format!("FemtoVG: Error making context current: {glutin_error}").into()
Expand All @@ -30,7 +25,6 @@ unsafe impl i_slint_renderer_femtovg::OpenGLContextWrapper for OpenGLContext {
Ok(())
}
fn swap_buffers(&self) -> Result<(), PlatformError> {
#[cfg(not(target_arch = "wasm32"))]
self.surface.swap_buffers(&self.context).map_err(|glutin_error| -> PlatformError {
format!("FemtoVG: Error swapping buffers: {glutin_error}").into()
})?;
Expand All @@ -39,35 +33,25 @@ unsafe impl i_slint_renderer_femtovg::OpenGLContextWrapper for OpenGLContext {
}

fn resize(&self, _size: PhysicalSize) -> Result<(), PlatformError> {
#[cfg(not(target_arch = "wasm32"))]
{
let width = _size.width.try_into().map_err(|_| {
format!(
"Attempting to create window surface with an invalid width: {}",
_size.width
)
})?;
let height = _size.height.try_into().map_err(|_| {
format!(
"Attempting to create window surface with an invalid height: {}",
_size.height
)
})?;
let width = _size.width.try_into().map_err(|_| {
format!("Attempting to create window surface with an invalid width: {}", _size.width)
})?;
let height = _size.height.try_into().map_err(|_| {
format!("Attempting to create window surface with an invalid height: {}", _size.height)
})?;

self.ensure_current()?;
self.surface.resize(&self.context, width, height);

self.ensure_current()?;
self.surface.resize(&self.context, width, height);
}
Ok(())
}

#[cfg(not(target_arch = "wasm32"))]
fn get_proc_address(&self, name: &std::ffi::CStr) -> *const std::ffi::c_void {
self.context.display().get_proc_address(name)
}
}

impl OpenGLContext {
#[cfg(not(target_arch = "wasm32"))]
pub fn new_context<T>(
window_builder: winit::window::WindowBuilder,
window_target: &winit::event_loop::EventLoopWindowTarget<T>,
Expand Down Expand Up @@ -181,18 +165,4 @@ impl OpenGLContext {

Ok((window, Self { context, surface }))
}

#[cfg(target_arch = "wasm32")]
pub fn new_context<T>(
window_builder: winit::window::WindowBuilder,
window_target: &winit::event_loop::EventLoopWindowTarget<T>,
) -> Result<(winit::window::Window, Self), PlatformError> {
let window = window_builder.build(window_target).map_err(|winit_os_err| {
format!(
"FemtoVG Renderer: Could not create winit window wrapper for DOM canvas: {}",
winit_os_err
)
})?;
Ok((window, Self {}))
}
}
22 changes: 21 additions & 1 deletion internal/renderers/femtovg/lib.rs
Expand Up @@ -49,6 +49,23 @@ pub unsafe trait OpenGLContextWrapper {
fn get_proc_address(&self, name: &std::ffi::CStr) -> *const std::ffi::c_void;
}

#[cfg(target_arch = "wasm32")]
struct WebGLNeedsNoCurrentContext;
#[cfg(target_arch = "wasm32")]
unsafe impl OpenGLContextWrapper for WebGLNeedsNoCurrentContext {
fn ensure_current(&self) -> Result<(), PlatformError> {
Ok(())
}

fn swap_buffers(&self) -> Result<(), PlatformError> {
Ok(())
}

fn resize(&self, _size: PhysicalWindowSize) -> Result<(), PlatformError> {
Ok(())
}
}

/// Use the FemtoVG renderer when implementing a custom Slint platform where you deliver events to
/// Slint and want the scene to be rendered using OpenGL and the FemtoVG renderer.
pub struct FemtoVGRenderer {
Expand All @@ -69,9 +86,12 @@ impl FemtoVGRenderer {
/// over when the make the context current, how to retrieve the address of GL functions, and when
/// to swap back and front buffers.
pub fn new(
opengl_context: impl OpenGLContextWrapper + 'static,
#[cfg(not(target_arch = "wasm32"))] opengl_context: impl OpenGLContextWrapper + 'static,
#[cfg(target_arch = "wasm32")] html_canvas: web_sys::HtmlCanvasElement,
) -> Result<Self, PlatformError> {
#[cfg(target_arch = "wasm32")]
let opengl_context = WebGLNeedsNoCurrentContext {};

let opengl_context = Box::new(opengl_context);
#[cfg(not(target_arch = "wasm32"))]
let gl_renderer = unsafe {
Expand Down

0 comments on commit af6b49a

Please sign in to comment.