Remove surface and window from ApplicationIo (#3941)

* Remove surface and window from ApplicationIo

* Seperate Wasm and Native ApplicationIo

* Fix warnings

* Fix tests

* Remove redundant PlatformApplicationIo::new_offscreen

* Fixup

* Remove unused From implementaitions for ApplicationIo
This commit is contained in:
Timon
2026-04-09 22:12:53 +02:00
committed by GitHub
parent b100892bfa
commit 661e8bc569
36 changed files with 716 additions and 773 deletions

View File

@@ -1,6 +1,6 @@
use core_types::transform::Footprint;
use dyn_any::{DynAny, StaticType, StaticTypeSized};
use glam::{DAffine2, DVec2, UVec2};
use glam::DVec2;
use std::fmt::Debug;
use std::future::Future;
use std::hash::{Hash, Hasher};
@@ -11,145 +11,36 @@ use std::time::Duration;
use text_nodes::FontCache;
use vector_types::vector::style::RenderMode;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct SurfaceId(pub u64);
impl std::fmt::Display for SurfaceId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}", self.0))
}
}
#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct SurfaceFrame {
pub surface_id: SurfaceId,
/// Logical resolution in CSS pixels (used for foreignObject dimensions)
pub resolution: DVec2,
pub transform: DAffine2,
}
impl Hash for SurfaceFrame {
fn hash<H: Hasher>(&self, state: &mut H) {
self.surface_id.hash(state);
self.transform.to_cols_array().iter().for_each(|x| x.to_bits().hash(state));
}
}
unsafe impl StaticType for SurfaceFrame {
type Static = SurfaceFrame;
}
pub trait Size {
fn size(&self) -> UVec2;
}
#[cfg(target_family = "wasm")]
impl Size for web_sys::HtmlCanvasElement {
fn size(&self) -> UVec2 {
UVec2::new(self.width(), self.height())
}
}
#[derive(Debug, Clone, DynAny)]
pub struct ImageTexture {
#[cfg(feature = "wgpu")]
pub texture: Arc<wgpu::Texture>,
#[cfg(not(feature = "wgpu"))]
pub texture: (),
}
impl<'a> serde::Deserialize<'a> for ImageTexture {
fn deserialize<D>(_: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'a>,
{
unimplemented!("attempted to serialize a texture")
}
}
impl Hash for ImageTexture {
#[cfg(feature = "wgpu")]
fn hash<H: Hasher>(&self, state: &mut H) {
self.texture.hash(state);
}
#[cfg(not(feature = "wgpu"))]
fn hash<H: Hasher>(&self, _state: &mut H) {}
}
impl PartialEq for ImageTexture {
fn eq(&self, other: &Self) -> bool {
#[cfg(feature = "wgpu")]
{
self.texture == other.texture
}
#[cfg(not(feature = "wgpu"))]
{
self.texture == other.texture
}
}
}
#[cfg(feature = "wgpu")]
impl Size for ImageTexture {
fn size(&self) -> UVec2 {
UVec2::new(self.texture.width(), self.texture.height())
#[derive(Debug, Clone, Hash, PartialEq, Eq, DynAny)]
pub struct ImageTexture(Arc<wgpu::Texture>);
#[cfg(feature = "wgpu")]
impl AsRef<wgpu::Texture> for ImageTexture {
fn as_ref(&self) -> &wgpu::Texture {
&self.0
}
}
impl<S: Size> From<SurfaceHandleFrame<S>> for SurfaceFrame {
fn from(x: SurfaceHandleFrame<S>) -> Self {
let size = x.surface_handle.surface.size();
Self {
surface_id: x.surface_handle.window_id,
transform: x.transform,
resolution: size.into(),
}
#[cfg(feature = "wgpu")]
impl From<wgpu::Texture> for ImageTexture {
fn from(texture: wgpu::Texture) -> Self {
Self(Arc::new(texture))
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SurfaceHandle<Surface> {
pub window_id: SurfaceId,
pub surface: Surface,
}
// #[cfg(target_family = "wasm")]
// unsafe impl<T: dyn_any::WasmNotSend> Send for SurfaceHandle<T> {}
// #[cfg(target_family = "wasm")]
// unsafe impl<T: dyn_any::WasmNotSync> Sync for SurfaceHandle<T> {}
impl<S: Size> Size for SurfaceHandle<S> {
fn size(&self) -> UVec2 {
self.surface.size()
#[cfg(feature = "wgpu")]
impl From<Arc<wgpu::Texture>> for ImageTexture {
fn from(texture: Arc<wgpu::Texture>) -> Self {
Self(texture)
}
}
unsafe impl<T: 'static> StaticType for SurfaceHandle<T> {
type Static = SurfaceHandle<T>;
}
#[derive(Clone, Debug, PartialEq)]
pub struct SurfaceHandleFrame<Surface> {
pub surface_handle: Arc<SurfaceHandle<Surface>>,
pub transform: DAffine2,
}
unsafe impl<T: 'static> StaticType for SurfaceHandleFrame<T> {
type Static = SurfaceHandleFrame<T>;
}
#[cfg(feature = "wasm")]
pub type WasmSurfaceHandle = SurfaceHandle<web_sys::HtmlCanvasElement>;
#[cfg(feature = "wasm")]
pub type WasmSurfaceHandleFrame = SurfaceHandleFrame<web_sys::HtmlCanvasElement>;
// TODO: think about how to automatically clean up memory
/*
impl<'a, Surface> Drop for SurfaceHandle<'a, Surface> {
fn drop(&mut self) {
self.application_io.destroy_surface(self.surface_id)
#[cfg(feature = "wgpu")]
impl From<ImageTexture> for Arc<wgpu::Texture> {
fn from(image_texture: ImageTexture) -> Self {
image_texture.0
}
}*/
}
#[cfg(not(feature = "wgpu"))]
#[derive(Debug, Clone, Hash, PartialEq, Eq, DynAny)]
pub struct ImageTexture;
#[cfg(target_family = "wasm")]
pub type ResourceFuture = Pin<Box<dyn Future<Output = Result<Arc<[u8]>, ApplicationError>>>>;
@@ -157,11 +48,7 @@ pub type ResourceFuture = Pin<Box<dyn Future<Output = Result<Arc<[u8]>, Applicat
pub type ResourceFuture = Pin<Box<dyn Future<Output = Result<Arc<[u8]>, ApplicationError>> + Send>>;
pub trait ApplicationIo {
type Surface;
type Executor;
fn window(&self) -> Option<SurfaceHandle<Self::Surface>>;
fn create_window(&self) -> SurfaceHandle<Self::Surface>;
fn destroy_window(&self, surface_id: SurfaceId);
fn gpu_executor(&self) -> Option<&Self::Executor> {
None
}
@@ -169,21 +56,8 @@ pub trait ApplicationIo {
}
impl<T: ApplicationIo> ApplicationIo for &T {
type Surface = T::Surface;
type Executor = T::Executor;
fn window(&self) -> Option<SurfaceHandle<Self::Surface>> {
(**self).window()
}
fn create_window(&self) -> SurfaceHandle<T::Surface> {
(**self).create_window()
}
fn destroy_window(&self, surface_id: SurfaceId) {
(**self).destroy_window(surface_id)
}
fn gpu_executor(&self) -> Option<&T::Executor> {
(**self).gpu_executor()
}
@@ -260,12 +134,12 @@ impl GetEditorPreferences for DummyPreferences {
}
pub struct EditorApi<Io> {
/// Font data (for rendering text) made available to the graph through the [`WasmEditorApi`].
/// Font data (for rendering text) made available to the graph through the `PlatformEditorApi`.
pub font_cache: FontCache,
/// Gives access to APIs like a rendering surface (native window handle or HTML5 canvas) and WGPU (which becomes WebGPU on web).
pub application_io: Option<Arc<Io>>,
pub node_graph_message_sender: Box<dyn NodeGraphUpdateSender + Send + Sync>,
/// Editor preferences made available to the graph through the [`WasmEditorApi`].
/// Editor preferences made available to the graph through the `PlatformEditorApi`.
pub editor_preferences: Box<dyn GetEditorPreferences + Send + Sync>,
}