diff options
-rw-r--r-- | Cargo.toml | 12 | ||||
-rw-r--r-- | core/Cargo.toml | 3 | ||||
-rw-r--r-- | examples/custom_shader/src/scene/pipeline.rs | 2 | ||||
-rw-r--r-- | examples/integration/src/main.rs | 12 | ||||
-rw-r--r-- | futures/src/lib.rs | 4 | ||||
-rw-r--r-- | futures/src/maybe.rs | 35 | ||||
-rw-r--r-- | futures/src/maybe_send.rs | 21 | ||||
-rw-r--r-- | graphics/Cargo.toml | 1 | ||||
-rw-r--r-- | graphics/src/compositor.rs | 27 | ||||
-rw-r--r-- | graphics/src/lib.rs | 1 | ||||
-rw-r--r-- | renderer/Cargo.toml | 1 | ||||
-rw-r--r-- | renderer/src/compositor.rs | 20 | ||||
-rw-r--r-- | tiny_skia/Cargo.toml | 1 | ||||
-rw-r--r-- | tiny_skia/src/window/compositor.rs | 113 | ||||
-rw-r--r-- | wgpu/Cargo.toml | 1 | ||||
-rw-r--r-- | wgpu/src/window/compositor.rs | 43 | ||||
-rw-r--r-- | winit/src/application.rs | 15 | ||||
-rw-r--r-- | winit/src/clipboard.rs | 3 | ||||
-rw-r--r-- | winit/src/multi_window.rs | 13 | ||||
-rw-r--r-- | winit/src/multi_window/window_manager.rs | 7 |
20 files changed, 207 insertions, 128 deletions
@@ -126,7 +126,7 @@ bytemuck = { version = "1.0", features = ["derive"] } cosmic-text = "0.10" futures = "0.3" glam = "0.24" -glyphon = "0.4" +glyphon = "0.5" guillotiere = "0.6" half = "2.2" image = "0.24" @@ -140,12 +140,12 @@ once_cell = "1.0" ouroboros = "0.17" palette = "0.7" qrcode = { version = "0.12", default-features = false } -raw-window-handle = "0.5" +raw-window-handle = "0.6" resvg = "0.36" rustc-hash = "1.0" smol = "1.0" smol_str = "0.2" -softbuffer = "0.2" +softbuffer = "0.4" syntect = "5.1" sysinfo = "0.28" thiserror = "1.0" @@ -158,7 +158,7 @@ wasm-bindgen-futures = "0.4" wasm-timer = "0.2" web-sys = "0.3" web-time = "0.2" -wgpu = "0.18" +wgpu = "0.19" winapi = "0.3" -window_clipboard = "0.3" -winit = { git = "https://github.com/iced-rs/winit.git", rev = "b91e39ece2c0d378c3b80da7f3ab50e17bb798a5", features = ["rwh_05"] } +window_clipboard = "0.4" +winit = { git = "https://github.com/iced-rs/winit.git", rev = "b91e39ece2c0d378c3b80da7f3ab50e17bb798a5" } diff --git a/core/Cargo.toml b/core/Cargo.toml index be92a572..32dd3df2 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -23,8 +23,7 @@ palette.workspace = true palette.optional = true [target.'cfg(windows)'.dependencies] -# TODO: Use `workspace` dependency once `wgpu` upgrades `raw-window-handle` -raw-window-handle = "0.6" +raw-window-handle.workspace = true [dev-dependencies] approx = "0.5" diff --git a/examples/custom_shader/src/scene/pipeline.rs b/examples/custom_shader/src/scene/pipeline.rs index 124b421f..50b70a98 100644 --- a/examples/custom_shader/src/scene/pipeline.rs +++ b/examples/custom_shader/src/scene/pipeline.rs @@ -97,6 +97,7 @@ impl Pipeline { usage: wgpu::TextureUsages::TEXTURE_BINDING, view_formats: &[], }, + wgpu::util::TextureDataOrder::LayerMajor, &normal_map_data, ); @@ -122,6 +123,7 @@ impl Pipeline { usage: wgpu::TextureUsages::TEXTURE_BINDING, view_formats: &[], }, + wgpu::util::TextureDataOrder::LayerMajor, &skybox_data, ); diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs index b0939d68..ed61459f 100644 --- a/examples/integration/src/main.rs +++ b/examples/integration/src/main.rs @@ -24,6 +24,8 @@ use winit::{ keyboard::ModifiersState, }; +use std::sync::Arc; + #[cfg(target_arch = "wasm32")] use wasm_bindgen::JsCast; #[cfg(target_arch = "wasm32")] @@ -59,6 +61,8 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> { #[cfg(not(target_arch = "wasm32"))] let window = winit::window::Window::new(&event_loop)?; + let window = Arc::new(window); + let physical_size = window.inner_size(); let mut viewport = Viewport::with_physical_size( Size::new(physical_size.width, physical_size.height), @@ -81,7 +85,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> { backends: backend, ..Default::default() }); - let surface = unsafe { instance.create_surface(&window) }?; + let surface = instance.create_surface(window.clone())?; let (format, (device, queue)) = futures::futures::executor::block_on(async { @@ -115,9 +119,9 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> { .request_device( &wgpu::DeviceDescriptor { label: None, - features: adapter_features + required_features: adapter_features & wgpu::Features::default(), - limits: needed_limits, + required_limits: needed_limits, }, None, ) @@ -136,6 +140,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> { present_mode: wgpu::PresentMode::AutoVsync, alpha_mode: wgpu::CompositeAlphaMode::Auto, view_formats: vec![], + desired_maximum_frame_latency: 2, }, ); @@ -188,6 +193,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> { present_mode: wgpu::PresentMode::AutoVsync, alpha_mode: wgpu::CompositeAlphaMode::Auto, view_formats: vec![], + desired_maximum_frame_latency: 2, }, ); diff --git a/futures/src/lib.rs b/futures/src/lib.rs index d54ba18a..b0acb76f 100644 --- a/futures/src/lib.rs +++ b/futures/src/lib.rs @@ -15,7 +15,7 @@ pub use futures; pub use iced_core as core; -mod maybe_send; +mod maybe; mod runtime; pub mod backend; @@ -25,7 +25,7 @@ pub mod keyboard; pub mod subscription; pub use executor::Executor; -pub use maybe_send::MaybeSend; +pub use maybe::{MaybeSend, MaybeSync}; pub use platform::*; pub use runtime::Runtime; pub use subscription::Subscription; diff --git a/futures/src/maybe.rs b/futures/src/maybe.rs new file mode 100644 index 00000000..c6a507c1 --- /dev/null +++ b/futures/src/maybe.rs @@ -0,0 +1,35 @@ +#[cfg(not(target_arch = "wasm32"))] +mod platform { + /// An extension trait that enforces `Send` only on native platforms. + /// + /// Useful for writing cross-platform async code! + pub trait MaybeSend: Send {} + + impl<T> MaybeSend for T where T: Send {} + + /// An extension trait that enforces `Sync` only on native platforms. + /// + /// Useful for writing cross-platform async code! + pub trait MaybeSync: Sync {} + + impl<T> MaybeSync for T where T: Sync {} +} + +#[cfg(target_arch = "wasm32")] +mod platform { + /// An extension trait that enforces `Send` only on native platforms. + /// + /// Useful for writing cross-platform async code! + pub trait MaybeSend {} + + impl<T> MaybeSend for T {} + + /// An extension trait that enforces `Sync` only on native platforms. + /// + /// Useful for writing cross-platform async code! + pub trait MaybeSync {} + + impl<T> MaybeSync for T {} +} + +pub use platform::{MaybeSend, MaybeSync}; diff --git a/futures/src/maybe_send.rs b/futures/src/maybe_send.rs deleted file mode 100644 index a6670f0e..00000000 --- a/futures/src/maybe_send.rs +++ /dev/null @@ -1,21 +0,0 @@ -#[cfg(not(target_arch = "wasm32"))] -mod platform { - /// An extension trait that enforces `Send` only on native platforms. - /// - /// Useful to write cross-platform async code! - pub trait MaybeSend: Send {} - - impl<T> MaybeSend for T where T: Send {} -} - -#[cfg(target_arch = "wasm32")] -mod platform { - /// An extension trait that enforces `Send` only on native platforms. - /// - /// Useful to write cross-platform async code! - pub trait MaybeSend {} - - impl<T> MaybeSend for T {} -} - -pub use platform::MaybeSend; diff --git a/graphics/Cargo.toml b/graphics/Cargo.toml index 6741d7cf..4f323f9e 100644 --- a/graphics/Cargo.toml +++ b/graphics/Cargo.toml @@ -21,6 +21,7 @@ web-colors = [] [dependencies] iced_core.workspace = true +iced_futures.workspace = true bitflags.workspace = true bytemuck.workspace = true diff --git a/graphics/src/compositor.rs b/graphics/src/compositor.rs index b8b575b4..0188f4d8 100644 --- a/graphics/src/compositor.rs +++ b/graphics/src/compositor.rs @@ -2,9 +2,10 @@ //! surfaces. use crate::{Error, Viewport}; -use iced_core::Color; +use crate::core::Color; +use crate::futures::{MaybeSend, MaybeSync}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use thiserror::Error; /// A graphics compositor that can draw to windows. @@ -19,9 +20,9 @@ pub trait Compositor: Sized { type Surface; /// Creates a new [`Compositor`]. - fn new<W: HasRawWindowHandle + HasRawDisplayHandle>( + fn new<W: Window + Clone>( settings: Self::Settings, - compatible_window: Option<&W>, + compatible_window: W, ) -> Result<Self, Error>; /// Creates a [`Self::Renderer`] for the [`Compositor`]. @@ -30,9 +31,9 @@ pub trait Compositor: Sized { /// Crates a new [`Surface`] for the given window. /// /// [`Surface`]: Self::Surface - fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>( + fn create_surface<W: Window + Clone>( &mut self, - window: &W, + window: W, width: u32, height: u32, ) -> Self::Surface; @@ -77,6 +78,20 @@ pub trait Compositor: Sized { ) -> Vec<u8>; } +/// A window that can be used in a [`Compositor`]. +/// +/// This is just a convenient super trait of the `raw-window-handle` +/// traits. +pub trait Window: + HasWindowHandle + HasDisplayHandle + MaybeSend + MaybeSync + 'static +{ +} + +impl<T> Window for T where + T: HasWindowHandle + HasDisplayHandle + MaybeSend + MaybeSync + 'static +{ +} + /// Result of an unsuccessful call to [`Compositor::present`]. #[derive(Clone, PartialEq, Eq, Debug, Error)] pub enum SurfaceError { diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs index 7a213909..76de56bf 100644 --- a/graphics/src/lib.rs +++ b/graphics/src/lib.rs @@ -50,3 +50,4 @@ pub use transformation::Transformation; pub use viewport::Viewport; pub use iced_core as core; +pub use iced_futures as futures; diff --git a/renderer/Cargo.toml b/renderer/Cargo.toml index 56e17209..a159978c 100644 --- a/renderer/Cargo.toml +++ b/renderer/Cargo.toml @@ -27,5 +27,4 @@ iced_wgpu.workspace = true iced_wgpu.optional = true log.workspace = true -raw-window-handle.workspace = true thiserror.workspace = true diff --git a/renderer/src/compositor.rs b/renderer/src/compositor.rs index 9d0ff9ab..f10ed048 100644 --- a/renderer/src/compositor.rs +++ b/renderer/src/compositor.rs @@ -1,9 +1,8 @@ use crate::core::Color; -use crate::graphics::compositor::{Information, SurfaceError}; +use crate::graphics::compositor::{Information, SurfaceError, Window}; use crate::graphics::{Error, Viewport}; use crate::{Renderer, Settings}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::env; pub enum Compositor<Theme> { @@ -15,7 +14,7 @@ pub enum Compositor<Theme> { pub enum Surface { TinySkia(iced_tiny_skia::window::Surface), #[cfg(feature = "wgpu")] - Wgpu(iced_wgpu::window::Surface), + Wgpu(iced_wgpu::window::Surface<'static>), } impl<Theme> crate::graphics::Compositor for Compositor<Theme> { @@ -23,9 +22,9 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> { type Renderer = Renderer<Theme>; type Surface = Surface; - fn new<W: HasRawWindowHandle + HasRawDisplayHandle>( + fn new<W: Window + Clone>( settings: Self::Settings, - compatible_window: Option<&W>, + compatible_window: W, ) -> Result<Self, Error> { let candidates = Candidate::list_from_env().unwrap_or(Candidate::default_list()); @@ -33,7 +32,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> { let mut error = Error::GraphicsAdapterNotFound; for candidate in candidates { - match candidate.build(settings, compatible_window) { + match candidate.build(settings, compatible_window.clone()) { Ok(compositor) => return Ok(compositor), Err(new_error) => { error = new_error; @@ -56,9 +55,9 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> { } } - fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>( + fn create_surface<W: Window + Clone>( &mut self, - window: &W, + window: W, width: u32, height: u32, ) -> Surface { @@ -226,10 +225,10 @@ impl Candidate { ) } - fn build<Theme, W: HasRawWindowHandle + HasRawDisplayHandle>( + fn build<Theme, W: Window>( self, settings: Settings, - _compatible_window: Option<&W>, + _compatible_window: W, ) -> Result<Compositor<Theme>, Error> { match self { Self::TinySkia => { @@ -238,6 +237,7 @@ impl Candidate { default_font: settings.default_font, default_text_size: settings.default_text_size, }, + _compatible_window, ); Ok(Compositor::TinySkia(compositor)) diff --git a/tiny_skia/Cargo.toml b/tiny_skia/Cargo.toml index df4c6143..68b2a03a 100644 --- a/tiny_skia/Cargo.toml +++ b/tiny_skia/Cargo.toml @@ -22,7 +22,6 @@ bytemuck.workspace = true cosmic-text.workspace = true kurbo.workspace = true log.workspace = true -raw-window-handle.workspace = true rustc-hash.workspace = true softbuffer.workspace = true tiny-skia.workspace = true diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 87ded746..781ed8a5 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -4,20 +4,25 @@ use crate::graphics::damage; use crate::graphics::{Error, Viewport}; use crate::{Backend, Primitive, Renderer, Settings}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; +use std::collections::VecDeque; use std::marker::PhantomData; +use std::num::NonZeroU32; pub struct Compositor<Theme> { + context: softbuffer::Context<Box<dyn compositor::Window>>, settings: Settings, _theme: PhantomData<Theme>, } pub struct Surface { - window: softbuffer::GraphicsContext, - buffer: Vec<u32>, + window: softbuffer::Surface< + Box<dyn compositor::Window>, + Box<dyn compositor::Window>, + >, clip_mask: tiny_skia::Mask, - primitives: Option<Vec<Primitive>>, + primitive_stack: VecDeque<Vec<Primitive>>, background_color: Color, + max_age: u8, } impl<Theme> crate::graphics::Compositor for Compositor<Theme> { @@ -25,11 +30,11 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> { type Renderer = Renderer<Theme>; type Surface = Surface; - fn new<W: HasRawWindowHandle + HasRawDisplayHandle>( + fn new<W: compositor::Window>( settings: Self::Settings, - _compatible_window: Option<&W>, + compatible_window: W, ) -> Result<Self, Error> { - Ok(new(settings)) + Ok(new(settings, compatible_window)) } fn create_renderer(&self) -> Self::Renderer { @@ -40,37 +45,49 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> { ) } - fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>( + fn create_surface<W: compositor::Window + Clone>( &mut self, - window: &W, + window: W, width: u32, height: u32, - ) -> Surface { - #[allow(unsafe_code)] - let window = - unsafe { softbuffer::GraphicsContext::new(window, window) } - .expect("Create softbuffer for window"); + ) -> Self::Surface { + let window = softbuffer::Surface::new( + &self.context, + Box::new(window.clone()) as _, + ) + .expect("Create softbuffer surface for window"); - Surface { + let mut surface = Surface { window, - buffer: vec![0; width as usize * height as usize], clip_mask: tiny_skia::Mask::new(width, height) .expect("Create clip mask"), - primitives: None, + primitive_stack: VecDeque::new(), background_color: Color::BLACK, - } + max_age: 0, + }; + + self.configure_surface(&mut surface, width, height); + + surface } fn configure_surface( &mut self, - surface: &mut Surface, + surface: &mut Self::Surface, width: u32, height: u32, ) { - surface.buffer.resize((width * height) as usize, 0); + surface + .window + .resize( + NonZeroU32::new(width).expect("Non-zero width"), + NonZeroU32::new(height).expect("Non-zero height"), + ) + .expect("Resize surface"); + surface.clip_mask = tiny_skia::Mask::new(width, height).expect("Create clip mask"); - surface.primitives = None; + surface.primitive_stack.clear(); } fn fetch_information(&self) -> Information { @@ -121,8 +138,16 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> { } } -pub fn new<Theme>(settings: Settings) -> Compositor<Theme> { +pub fn new<W: compositor::Window, Theme>( + settings: Settings, + compatible_window: W, +) -> Compositor<Theme> { + #[allow(unsafe_code)] + let context = softbuffer::Context::new(Box::new(compatible_window) as _) + .expect("Create softbuffer context"); + Compositor { + context, settings, _theme: PhantomData, } @@ -139,16 +164,25 @@ pub fn present<T: AsRef<str>>( let physical_size = viewport.physical_size(); let scale_factor = viewport.scale_factor() as f32; - let mut pixels = tiny_skia::PixmapMut::from_bytes( - bytemuck::cast_slice_mut(&mut surface.buffer), - physical_size.width, - physical_size.height, - ) - .expect("Create pixel map"); + let mut buffer = surface + .window + .buffer_mut() + .map_err(|_| compositor::SurfaceError::Lost)?; + + let last_primitives = { + let age = buffer.age(); - let damage = surface - .primitives - .as_deref() + surface.max_age = surface.max_age.max(age); + surface.primitive_stack.truncate(surface.max_age as usize); + + if age > 0 { + surface.primitive_stack.get(age as usize - 1) + } else { + None + } + }; + + let damage = last_primitives .and_then(|last_primitives| { (surface.background_color == background_color) .then(|| damage::list(last_primitives, primitives)) @@ -159,11 +193,18 @@ pub fn present<T: AsRef<str>>( return Ok(()); } - surface.primitives = Some(primitives.to_vec()); + surface.primitive_stack.push_front(primitives.to_vec()); surface.background_color = background_color; let damage = damage::group(damage, scale_factor, physical_size); + let mut pixels = tiny_skia::PixmapMut::from_bytes( + bytemuck::cast_slice_mut(&mut buffer), + physical_size.width, + physical_size.height, + ) + .expect("Create pixel map"); + backend.draw( &mut pixels, &mut surface.clip_mask, @@ -174,13 +215,7 @@ pub fn present<T: AsRef<str>>( overlay, ); - surface.window.set_buffer( - &surface.buffer, - physical_size.width as u16, - physical_size.height as u16, - ); - - Ok(()) + buffer.present().map_err(|_| compositor::SurfaceError::Lost) } pub fn screenshot<T: AsRef<str>>( diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index a460c127..1d3b57a7 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -32,7 +32,6 @@ glyphon.workspace = true guillotiere.workspace = true log.workspace = true once_cell.workspace = true -raw-window-handle.workspace = true wgpu.workspace = true lyon.workspace = true diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index 090e0e9f..31cf3819 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -6,8 +6,6 @@ use crate::graphics::compositor; use crate::graphics::{Error, Viewport}; use crate::{Backend, Primitive, Renderer, Settings}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; - use std::marker::PhantomData; /// A window graphics backend for iced powered by `wgpu`. @@ -26,9 +24,9 @@ impl<Theme> Compositor<Theme> { /// Requests a new [`Compositor`] with the given [`Settings`]. /// /// Returns `None` if no compatible graphics adapter could be found. - pub async fn request<W: HasRawWindowHandle + HasRawDisplayHandle>( + pub async fn request<W: compositor::Window>( settings: Settings, - compatible_window: Option<&W>, + compatible_window: Option<W>, ) -> Option<Self> { let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { backends: settings.internal_backend, @@ -41,14 +39,15 @@ impl<Theme> Compositor<Theme> { if log::max_level() >= log::LevelFilter::Info { let available_adapters: Vec<_> = instance .enumerate_adapters(settings.internal_backend) - .map(|adapter| adapter.get_info()) + .iter() + .map(wgpu::Adapter::get_info) .collect(); log::info!("Available adapters: {available_adapters:#?}"); } #[allow(unsafe_code)] let compatible_surface = compatible_window - .and_then(|window| unsafe { instance.create_surface(window).ok() }); + .and_then(|window| instance.create_surface(window).ok()); let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -100,14 +99,14 @@ impl<Theme> Compositor<Theme> { let (device, queue) = loop { - let limits = limits.next()?; + let required_limits = limits.next()?; let device = adapter.request_device( &wgpu::DeviceDescriptor { label: Some( "iced_wgpu::window::compositor device descriptor", ), - features: wgpu::Features::empty(), - limits, + required_features: wgpu::Features::empty(), + required_limits, }, None, ).await.ok(); @@ -136,13 +135,13 @@ impl<Theme> Compositor<Theme> { /// Creates a [`Compositor`] and its [`Backend`] for the given [`Settings`] and /// window. -pub fn new<Theme, W: HasRawWindowHandle + HasRawDisplayHandle>( +pub fn new<W: compositor::Window, Theme>( settings: Settings, - compatible_window: Option<&W>, + compatible_window: W, ) -> Result<Compositor<Theme>, Error> { let compositor = futures::executor::block_on(Compositor::request( settings, - compatible_window, + Some(compatible_window), )) .ok_or(Error::GraphicsAdapterNotFound)?; @@ -153,7 +152,7 @@ pub fn new<Theme, W: HasRawWindowHandle + HasRawDisplayHandle>( pub fn present<Theme, T: AsRef<str>>( compositor: &mut Compositor<Theme>, backend: &mut Backend, - surface: &mut wgpu::Surface, + surface: &mut wgpu::Surface<'static>, primitives: &[Primitive], viewport: &Viewport, background_color: Color, @@ -207,11 +206,11 @@ pub fn present<Theme, T: AsRef<str>>( impl<Theme> graphics::Compositor for Compositor<Theme> { type Settings = Settings; type Renderer = Renderer<Theme>; - type Surface = wgpu::Surface; + type Surface = wgpu::Surface<'static>; - fn new<W: HasRawWindowHandle + HasRawDisplayHandle>( + fn new<W: compositor::Window>( settings: Self::Settings, - compatible_window: Option<&W>, + compatible_window: W, ) -> Result<Self, Error> { new(settings, compatible_window) } @@ -224,14 +223,15 @@ impl<Theme> graphics::Compositor for Compositor<Theme> { ) } - fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>( + fn create_surface<W: compositor::Window>( &mut self, - window: &W, + window: W, width: u32, height: u32, - ) -> wgpu::Surface { - #[allow(unsafe_code)] - let mut surface = unsafe { self.instance.create_surface(window) } + ) -> Self::Surface { + let mut surface = self + .instance + .create_surface(window) .expect("Create surface"); self.configure_surface(&mut surface, width, height); @@ -255,6 +255,7 @@ impl<Theme> graphics::Compositor for Compositor<Theme> { height, alpha_mode: wgpu::CompositeAlphaMode::Auto, view_formats: vec![], + desired_maximum_frame_latency: 2, }, ); } diff --git a/winit/src/application.rs b/winit/src/application.rs index bf48538d..09bf63cc 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -24,6 +24,7 @@ use crate::{Clipboard, Error, Proxy, Settings}; use futures::channel::mpsc; use std::mem::ManuallyDrop; +use std::sync::Arc; /// An interactive, native cross-platform application. /// @@ -149,9 +150,11 @@ where log::debug!("Window builder: {builder:#?}"); - let window = builder - .build(&event_loop) - .map_err(Error::WindowCreationFailed)?; + let window = Arc::new( + builder + .build(&event_loop) + .map_err(Error::WindowCreationFailed)?, + ); #[cfg(target_arch = "wasm32")] { @@ -183,7 +186,7 @@ where }; } - let compositor = C::new(compositor_settings, Some(&window))?; + let compositor = C::new(compositor_settings, window.clone())?; let mut renderer = compositor.create_renderer(); for font in settings.fonts { @@ -248,7 +251,7 @@ async fn run_instance<A, E, C>( >, mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>, init_command: Command<A::Message>, - window: winit::window::Window, + window: Arc<winit::window::Window>, should_be_visible: bool, exit_on_close_request: bool, ) where @@ -268,7 +271,7 @@ async fn run_instance<A, E, C>( let mut clipboard = Clipboard::connect(&window); let mut cache = user_interface::Cache::default(); let mut surface = compositor.create_surface( - &window, + window.clone(), physical_size.width, physical_size.height, ); diff --git a/winit/src/clipboard.rs b/winit/src/clipboard.rs index f7a32868..8f5c5e63 100644 --- a/winit/src/clipboard.rs +++ b/winit/src/clipboard.rs @@ -15,7 +15,8 @@ enum State { impl Clipboard { /// Creates a new [`Clipboard`] for the given window. pub fn connect(window: &winit::window::Window) -> Clipboard { - let state = window_clipboard::Clipboard::connect(window) + #[allow(unsafe_code)] + let state = unsafe { window_clipboard::Clipboard::connect(window) } .ok() .map(State::Connected) .unwrap_or(State::Unavailable); diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs index 84c81bea..3f0ba056 100644 --- a/winit/src/multi_window.rs +++ b/winit/src/multi_window.rs @@ -24,6 +24,7 @@ use crate::{Clipboard, Error, Proxy, Settings}; use std::collections::HashMap; use std::mem::ManuallyDrop; +use std::sync::Arc; use std::time::Instant; /// An interactive, native, cross-platform, multi-windowed application. @@ -150,9 +151,11 @@ where log::info!("Window builder: {:#?}", builder); - let main_window = builder - .build(&event_loop) - .map_err(Error::WindowCreationFailed)?; + let main_window = Arc::new( + builder + .build(&event_loop) + .map_err(Error::WindowCreationFailed)?, + ); #[cfg(target_arch = "wasm32")] { @@ -184,7 +187,7 @@ where }; } - let mut compositor = C::new(compositor_settings, Some(&main_window))?; + let mut compositor = C::new(compositor_settings, main_window.clone())?; let mut window_manager = WindowManager::new(); let _ = window_manager.insert( @@ -388,7 +391,7 @@ async fn run_instance<A, E, C>( } => { let window = window_manager.insert( id, - window, + Arc::new(window), &application, &mut compositor, exit_on_close_request, diff --git a/winit/src/multi_window/window_manager.rs b/winit/src/multi_window/window_manager.rs index d54156e7..9e15f9ea 100644 --- a/winit/src/multi_window/window_manager.rs +++ b/winit/src/multi_window/window_manager.rs @@ -6,6 +6,7 @@ use crate::multi_window::{Application, State}; use crate::style::application::StyleSheet; use std::collections::BTreeMap; +use std::sync::Arc; use winit::monitor::MonitorHandle; #[allow(missing_debug_implementations)] @@ -34,7 +35,7 @@ where pub fn insert( &mut self, id: Id, - window: winit::window::Window, + window: Arc<winit::window::Window>, application: &A, compositor: &mut C, exit_on_close_request: bool, @@ -43,7 +44,7 @@ where let viewport_version = state.viewport_version(); let physical_size = state.physical_size(); let surface = compositor.create_surface( - &window, + window.clone(), physical_size.width, physical_size.height, ); @@ -122,7 +123,7 @@ where C: Compositor<Renderer = A::Renderer>, <A::Renderer as crate::core::Renderer>::Theme: StyleSheet, { - pub raw: winit::window::Window, + pub raw: Arc<winit::window::Window>, pub state: State<A>, pub viewport_version: u64, pub exit_on_close_request: bool, |