From ff268c8c4268d930fc337636302175d44e201448 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 9 Jan 2024 12:25:53 -0800 Subject: Update to `softbuffer` 0.3, tracking up to `age` sets of primitives --- Cargo.toml | 2 +- renderer/src/compositor.rs | 1 + tiny_skia/src/window/compositor.rs | 121 +++++++++++++++++++++++-------------- 3 files changed, 79 insertions(+), 45 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ac72f212..1f2da434 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -145,7 +145,7 @@ resvg = "0.36" rustc-hash = "1.0" smol = "1.0" smol_str = "0.2" -softbuffer = "0.2" +softbuffer = "0.3.4" syntect = "5.1" sysinfo = "0.28" thiserror = "1.0" diff --git a/renderer/src/compositor.rs b/renderer/src/compositor.rs index 9d0ff9ab..f9afdea4 100644 --- a/renderer/src/compositor.rs +++ b/renderer/src/compositor.rs @@ -238,6 +238,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/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 87ded746..d99b85d4 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -5,18 +5,21 @@ 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 { + context: Option, settings: Settings, _theme: PhantomData, } pub struct Surface { - window: softbuffer::GraphicsContext, - buffer: Vec, + window: softbuffer::Surface, clip_mask: tiny_skia::Mask, - primitives: Option>, + // Primitives of existing buffers, by decreasing age + primitives: VecDeque>, background_color: Color, } @@ -27,9 +30,9 @@ impl crate::graphics::Compositor for Compositor { fn new( settings: Self::Settings, - _compatible_window: Option<&W>, + compatible_window: Option<&W>, ) -> Result { - Ok(new(settings)) + Ok(new(settings, compatible_window)) } fn create_renderer(&self) -> Self::Renderer { @@ -47,16 +50,21 @@ impl crate::graphics::Compositor for Compositor { height: u32, ) -> Surface { #[allow(unsafe_code)] - let window = - unsafe { softbuffer::GraphicsContext::new(window, window) } - .expect("Create softbuffer for window"); + let window = if let Some(context) = self.context.as_ref() { + unsafe { softbuffer::Surface::new(context, window) } + .expect("Create softbuffer surface for window") + } else { + let context = unsafe { softbuffer::Context::new(window) } + .expect("Create softbuffer context for window"); + unsafe { softbuffer::Surface::new(&context, window) } + .expect("Create softbuffer surface for window") + }; 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, + primitives: VecDeque::new(), background_color: Color::BLACK, } } @@ -67,10 +75,9 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) { - surface.buffer.resize((width * height) as usize, 0); surface.clip_mask = tiny_skia::Mask::new(width, height).expect("Create clip mask"); - surface.primitives = None; + surface.primitives.clear(); } fn fetch_information(&self) -> Information { @@ -121,8 +128,15 @@ impl crate::graphics::Compositor for Compositor { } } -pub fn new(settings: Settings) -> Compositor { +pub fn new( + settings: Settings, + compatible_window: Option<&W>, +) -> Compositor { + #[allow(unsafe_code)] + let context = compatible_window + .and_then(|w| unsafe { softbuffer::Context::new(w) }.ok()); Compositor { + context, settings, _theme: PhantomData, } @@ -139,48 +153,67 @@ pub fn present>( 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"); + surface + .window + .resize( + NonZeroU32::new(physical_size.width).unwrap(), + NonZeroU32::new(physical_size.height).unwrap(), + ) + .unwrap(); + + // TODO Add variants to `SurfaceError`? + let mut buffer = surface + .window + .buffer_mut() + .map_err(|_| compositor::SurfaceError::Lost)?; + + let age = buffer.age(); - let damage = surface - .primitives - .as_deref() + // Forget primatives for back buffers older than `age` + // Or if this is a new buffer, keep at most two. + let max = if age == 0 { 2 } else { age }; + while surface.primitives.len() as u8 > max { + let _ = surface.primitives.pop_front(); + } + + let last_primitives = if surface.primitives.len() as u8 == age { + surface.primitives.pop_front() + } else { + None + }; + + let damage = last_primitives .and_then(|last_primitives| { (surface.background_color == background_color) - .then(|| damage::list(last_primitives, primitives)) + .then(|| damage::list(&last_primitives, primitives)) }) .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); - if damage.is_empty() { - return Ok(()); - } - - surface.primitives = Some(primitives.to_vec()); + surface.primitives.push_back(primitives.to_vec()); surface.background_color = background_color; - let damage = damage::group(damage, scale_factor, physical_size); + if !damage.is_empty() { + let damage = damage::group(damage, scale_factor, physical_size); - backend.draw( - &mut pixels, - &mut surface.clip_mask, - primitives, - viewport, - &damage, - background_color, - overlay, - ); + let mut pixels = tiny_skia::PixmapMut::from_bytes( + bytemuck::cast_slice_mut(&mut buffer), + physical_size.width, + physical_size.height, + ) + .expect("Create pixel map"); - surface.window.set_buffer( - &surface.buffer, - physical_size.width as u16, - physical_size.height as u16, - ); + backend.draw( + &mut pixels, + &mut surface.clip_mask, + primitives, + viewport, + &damage, + background_color, + overlay, + ); + } - Ok(()) + buffer.present().map_err(|_| compositor::SurfaceError::Lost) } pub fn screenshot>( -- cgit From 7289b6091b61b0aa448a756cfe32211c78a4cce0 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 9 Jan 2024 07:19:15 -0800 Subject: WIP raw-window-handle 0.6 --- Cargo.toml | 18 ++++++---- graphics/src/compositor.rs | 12 +++---- renderer/src/compositor.rs | 51 ++++++++++++++------------ src/application.rs | 7 +++- tiny_skia/src/window/compositor.rs | 56 +++++++++++++++-------------- wgpu/src/window/compositor.rs | 73 +++++++++++++++++++++++--------------- winit/src/application.rs | 24 +++++++------ winit/src/clipboard.rs | 3 +- 8 files changed, 142 insertions(+), 102 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1f2da434..421c7c76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,6 +70,8 @@ thiserror.workspace = true image.workspace = true image.optional = true +winit.workspace = true + [profile.release-opt] inherits = "release" codegen-units = 1 @@ -126,7 +128,10 @@ bytemuck = { version = "1.0", features = ["derive"] } cosmic-text = "0.10" futures = "0.3" glam = "0.24" -glyphon = "0.4" +# glyphon = "0.4" +# TODO update for wgpu 0.19 +# https://github.com/grovesNL/glyphon/pull/80 +glyphon = { git = "https://github.com/EggShark/glyphon" } guillotiere = "0.6" half = "2.2" image = "0.24" @@ -140,12 +145,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.3.4" +softbuffer = "0.4.1" syntect = "5.1" sysinfo = "0.28" thiserror = "1.0" @@ -158,7 +163,8 @@ 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.3" +window_clipboard = { git = "https://github.com/ids1024/window_clipboard", branch = "raw-window-handle-0.6" } +winit = { git = "https://github.com/iced-rs/winit.git", rev = "b91e39ece2c0d378c3b80da7f3ab50e17bb798a5", features = ["rwh_06"] } diff --git a/graphics/src/compositor.rs b/graphics/src/compositor.rs index b8b575b4..6a4c7909 100644 --- a/graphics/src/compositor.rs +++ b/graphics/src/compositor.rs @@ -4,11 +4,11 @@ use crate::{Error, Viewport}; use iced_core::Color; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use thiserror::Error; /// A graphics compositor that can draw to windows. -pub trait Compositor: Sized { +pub trait Compositor: Sized { /// The settings of the backend. type Settings: Default; @@ -19,9 +19,9 @@ pub trait Compositor: Sized { type Surface; /// Creates a new [`Compositor`]. - fn new( + fn new( settings: Self::Settings, - compatible_window: Option<&W>, + compatible_window: Option, ) -> Result; /// Creates a [`Self::Renderer`] for the [`Compositor`]. @@ -30,9 +30,9 @@ pub trait Compositor: Sized { /// Crates a new [`Surface`] for the given window. /// /// [`Surface`]: Self::Surface - fn create_surface( + fn create_surface( &mut self, - window: &W, + window: W, width: u32, height: u32, ) -> Self::Surface; diff --git a/renderer/src/compositor.rs b/renderer/src/compositor.rs index f9afdea4..17157c66 100644 --- a/renderer/src/compositor.rs +++ b/renderer/src/compositor.rs @@ -3,29 +3,36 @@ use crate::graphics::compositor::{Information, SurfaceError}; use crate::graphics::{Error, Viewport}; use crate::{Renderer, Settings}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use std::env; -pub enum Compositor { - TinySkia(iced_tiny_skia::window::Compositor), +pub enum Compositor { + TinySkia(iced_tiny_skia::window::Compositor), #[cfg(feature = "wgpu")] - Wgpu(iced_wgpu::window::Compositor), + Wgpu(iced_wgpu::window::Compositor), } -pub enum Surface { - TinySkia(iced_tiny_skia::window::Surface), +pub enum Surface { + TinySkia(iced_tiny_skia::window::Surface), #[cfg(feature = "wgpu")] - Wgpu(iced_wgpu::window::Surface), + Wgpu(iced_wgpu::window::Surface<'static>), } -impl crate::graphics::Compositor for Compositor { +// XXX Clone bound +// XXX Send/Sync? +// 'static? +impl< + W: Clone + Send + Sync + HasWindowHandle + HasDisplayHandle + 'static, + Theme, + > crate::graphics::Compositor for Compositor +{ type Settings = Settings; type Renderer = Renderer; - type Surface = Surface; + type Surface = Surface; - fn new( + fn new( settings: Self::Settings, - compatible_window: Option<&W>, + compatible_window: Option, ) -> Result { let candidates = Candidate::list_from_env().unwrap_or(Candidate::default_list()); @@ -33,7 +40,7 @@ impl crate::graphics::Compositor for Compositor { 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,12 +63,12 @@ impl crate::graphics::Compositor for Compositor { } } - fn create_surface( + fn create_surface( &mut self, - window: &W, + window: W, width: u32, height: u32, - ) -> Surface { + ) -> Surface { match self { Self::TinySkia(compositor) => Surface::TinySkia( compositor.create_surface(window, width, height), @@ -75,7 +82,7 @@ impl crate::graphics::Compositor for Compositor { fn configure_surface( &mut self, - surface: &mut Surface, + surface: &mut Surface, width: u32, height: u32, ) { @@ -114,7 +121,7 @@ impl crate::graphics::Compositor for Compositor { ( Self::TinySkia(_compositor), crate::Renderer::TinySkia(renderer), - Surface::TinySkia(surface), + Surface::TinySkia(ref mut surface), ) => renderer.with_primitives(|backend, primitives| { iced_tiny_skia::window::compositor::present( backend, @@ -129,7 +136,7 @@ impl crate::graphics::Compositor for Compositor { ( Self::Wgpu(compositor), crate::Renderer::Wgpu(renderer), - Surface::Wgpu(surface), + Surface::Wgpu(ref mut surface), ) => renderer.with_primitives(|backend, primitives| { iced_wgpu::window::compositor::present( compositor, @@ -161,7 +168,7 @@ impl crate::graphics::Compositor for Compositor { ( Self::TinySkia(_compositor), Renderer::TinySkia(renderer), - Surface::TinySkia(surface), + Surface::TinySkia(ref mut surface), ) => renderer.with_primitives(|backend, primitives| { iced_tiny_skia::window::compositor::screenshot( surface, @@ -226,11 +233,11 @@ impl Candidate { ) } - fn build( + fn build( self, settings: Settings, - _compatible_window: Option<&W>, - ) -> Result, Error> { + _compatible_window: Option, + ) -> Result, Error> { match self { Self::TinySkia => { let compositor = iced_tiny_skia::window::compositor::new( diff --git a/src/application.rs b/src/application.rs index 9518b8c5..d7be6719 100644 --- a/src/application.rs +++ b/src/application.rs @@ -1,6 +1,8 @@ //! Build interactive cross-platform applications. use crate::{Command, Element, Executor, Settings, Subscription}; +use std::sync::Arc; + pub use crate::style::application::{Appearance, StyleSheet}; /// An interactive cross-platform application. @@ -208,7 +210,10 @@ pub trait Application: Sized { Ok(crate::shell::application::run::< Instance, Self::Executor, - crate::renderer::Compositor, + crate::renderer::Compositor< + Arc, + Self::Theme, + >, >(settings.into(), renderer_settings)?) } } diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index d99b85d4..788d7297 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -4,33 +4,36 @@ use crate::graphics::damage; use crate::graphics::{Error, Viewport}; use crate::{Backend, Primitive, Renderer, Settings}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use std::collections::VecDeque; use std::marker::PhantomData; use std::num::NonZeroU32; -pub struct Compositor { - context: Option, +pub struct Compositor { + context: Option>, settings: Settings, _theme: PhantomData, } -pub struct Surface { - window: softbuffer::Surface, +pub struct Surface { + window: softbuffer::Surface, clip_mask: tiny_skia::Mask, // Primitives of existing buffers, by decreasing age primitives: VecDeque>, background_color: Color, } -impl crate::graphics::Compositor for Compositor { +// XXX avoid clone bound? +impl + crate::graphics::Compositor for Compositor +{ type Settings = Settings; type Renderer = Renderer; - type Surface = Surface; + type Surface = Surface; - fn new( + fn new( settings: Self::Settings, - compatible_window: Option<&W>, + compatible_window: Option, ) -> Result { Ok(new(settings, compatible_window)) } @@ -43,20 +46,19 @@ impl crate::graphics::Compositor for Compositor { ) } - fn create_surface( + fn create_surface( &mut self, - window: &W, + window: W, width: u32, height: u32, - ) -> Surface { - #[allow(unsafe_code)] + ) -> Surface { let window = if let Some(context) = self.context.as_ref() { - unsafe { softbuffer::Surface::new(context, window) } + softbuffer::Surface::new(context, window) .expect("Create softbuffer surface for window") } else { - let context = unsafe { softbuffer::Context::new(window) } + let context = softbuffer::Context::new(window.clone()) .expect("Create softbuffer context for window"); - unsafe { softbuffer::Surface::new(&context, window) } + softbuffer::Surface::new(&context, window) .expect("Create softbuffer surface for window") }; @@ -71,7 +73,7 @@ impl crate::graphics::Compositor for Compositor { fn configure_surface( &mut self, - surface: &mut Surface, + surface: &mut Surface, width: u32, height: u32, ) { @@ -90,7 +92,7 @@ impl crate::graphics::Compositor for Compositor { fn present>( &mut self, renderer: &mut Self::Renderer, - surface: &mut Self::Surface, + surface: &mut Surface, viewport: &Viewport, background_color: Color, overlay: &[T], @@ -128,13 +130,13 @@ impl crate::graphics::Compositor for Compositor { } } -pub fn new( +pub fn new( settings: Settings, - compatible_window: Option<&W>, -) -> Compositor { + compatible_window: Option, +) -> Compositor { #[allow(unsafe_code)] - let context = compatible_window - .and_then(|w| unsafe { softbuffer::Context::new(w) }.ok()); + let context = + compatible_window.and_then(|w| softbuffer::Context::new(w).ok()); Compositor { context, settings, @@ -142,9 +144,9 @@ pub fn new( } } -pub fn present>( +pub fn present>( backend: &mut Backend, - surface: &mut Surface, + surface: &mut Surface, primitives: &[Primitive], viewport: &Viewport, background_color: Color, @@ -216,8 +218,8 @@ pub fn present>( buffer.present().map_err(|_| compositor::SurfaceError::Lost) } -pub fn screenshot>( - surface: &mut Surface, +pub fn screenshot>( + surface: &mut Surface, backend: &mut Backend, primitives: &[Primitive], viewport: &Viewport, diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index 090e0e9f..e2dc4901 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -6,13 +6,13 @@ use crate::graphics::compositor; use crate::graphics::{Error, Viewport}; use crate::{Backend, Primitive, Renderer, Settings}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use std::marker::PhantomData; /// A window graphics backend for iced powered by `wgpu`. #[allow(missing_debug_implementations)] -pub struct Compositor { +pub struct Compositor { settings: Settings, instance: wgpu::Instance, adapter: wgpu::Adapter, @@ -20,15 +20,18 @@ pub struct Compositor { queue: wgpu::Queue, format: wgpu::TextureFormat, theme: PhantomData, + w: PhantomData, } -impl Compositor { +impl + Compositor +{ /// Requests a new [`Compositor`] with the given [`Settings`]. /// /// Returns `None` if no compatible graphics adapter could be found. - pub async fn request( + pub async fn request( settings: Settings, - compatible_window: Option<&W>, + compatible_window: Option, ) -> Option { let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { backends: settings.internal_backend, @@ -41,6 +44,7 @@ impl Compositor { if log::max_level() >= log::LevelFilter::Info { let available_adapters: Vec<_> = instance .enumerate_adapters(settings.internal_backend) + .iter() .map(|adapter| adapter.get_info()) .collect(); log::info!("Available adapters: {available_adapters:#?}"); @@ -48,7 +52,7 @@ impl Compositor { #[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 +104,14 @@ impl Compositor { 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(); @@ -125,6 +129,7 @@ impl Compositor { queue, format, theme: PhantomData, + w: PhantomData, }) } @@ -136,10 +141,13 @@ impl Compositor { /// Creates a [`Compositor`] and its [`Backend`] for the given [`Settings`] and /// window. -pub fn new( +pub fn new< + Theme, + W: HasWindowHandle + HasDisplayHandle + wgpu::WasmNotSendSync, +>( settings: Settings, - compatible_window: Option<&W>, -) -> Result, Error> { + compatible_window: Option, +) -> Result, Error> { let compositor = futures::executor::block_on(Compositor::request( settings, compatible_window, @@ -150,10 +158,10 @@ pub fn new( } /// Presents the given primitives with the given [`Compositor`] and [`Backend`]. -pub fn present>( - compositor: &mut Compositor, +pub fn present>( + compositor: &mut Compositor, backend: &mut Backend, - surface: &mut wgpu::Surface, + surface: &mut wgpu::Surface<'static>, primitives: &[Primitive], viewport: &Viewport, background_color: Color, @@ -204,14 +212,19 @@ pub fn present>( } } -impl graphics::Compositor for Compositor { +impl< + W: HasDisplayHandle + HasWindowHandle + wgpu::WasmNotSendSync + 'static, + Theme, + > graphics::Compositor for Compositor +{ type Settings = Settings; type Renderer = Renderer; - type Surface = wgpu::Surface; + // XXX generic instead of 'static + type Surface = wgpu::Surface<'static>; - fn new( + fn new( settings: Self::Settings, - compatible_window: Option<&W>, + compatible_window: Option, ) -> Result { new(settings, compatible_window) } @@ -224,14 +237,15 @@ impl graphics::Compositor for Compositor { ) } - fn create_surface( + fn create_surface( &mut self, - window: &W, + window: W, width: u32, height: u32, - ) -> wgpu::Surface { - #[allow(unsafe_code)] - let mut surface = unsafe { self.instance.create_surface(window) } + ) -> wgpu::Surface<'static> { + let mut surface = self + .instance + .create_surface(window) .expect("Create surface"); self.configure_surface(&mut surface, width, height); @@ -241,7 +255,7 @@ impl graphics::Compositor for Compositor { fn configure_surface( &mut self, - surface: &mut Self::Surface, + surface: &mut wgpu::Surface<'static>, width: u32, height: u32, ) { @@ -255,6 +269,7 @@ impl graphics::Compositor for Compositor { height, alpha_mode: wgpu::CompositeAlphaMode::Auto, view_formats: vec![], + desired_maximum_frame_latency: 2, }, ); } @@ -271,7 +286,7 @@ impl graphics::Compositor for Compositor { fn present>( &mut self, renderer: &mut Self::Renderer, - surface: &mut Self::Surface, + surface: &mut wgpu::Surface<'static>, viewport: &Viewport, background_color: Color, overlay: &[T], @@ -292,7 +307,7 @@ impl graphics::Compositor for Compositor { fn screenshot>( &mut self, renderer: &mut Self::Renderer, - _surface: &mut Self::Surface, + _surface: &mut wgpu::Surface<'static>, viewport: &Viewport, background_color: Color, overlay: &[T], @@ -313,8 +328,8 @@ impl graphics::Compositor for Compositor { /// Renders the current surface to an offscreen buffer. /// /// Returns RGBA bytes of the texture data. -pub fn screenshot>( - compositor: &Compositor, +pub fn screenshot>( + compositor: &Compositor, backend: &mut Backend, primitives: &[Primitive], viewport: &Viewport, diff --git a/winit/src/application.rs b/winit/src/application.rs index bf48538d..d639a36b 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. /// @@ -105,7 +106,7 @@ pub fn run( where A: Application + 'static, E: Executor + 'static, - C: Compositor + 'static, + C: Compositor, Renderer = A::Renderer> + 'static, ::Theme: StyleSheet, { use futures::task; @@ -149,9 +150,12 @@ where log::debug!("Window builder: {builder:#?}"); - let window = builder - .build(&event_loop) - .map_err(Error::WindowCreationFailed)?; + // XXX Arc? + let window = Arc::new( + builder + .build(&event_loop) + .map_err(Error::WindowCreationFailed)?, + ); #[cfg(target_arch = "wasm32")] { @@ -183,7 +187,7 @@ where }; } - let compositor = C::new(compositor_settings, Some(&window))?; + let compositor = C::new(compositor_settings, Some(window.clone()))?; let mut renderer = compositor.create_renderer(); for font in settings.fonts { @@ -248,13 +252,13 @@ async fn run_instance( >, mut control_sender: mpsc::UnboundedSender, init_command: Command, - window: winit::window::Window, + window: Arc, should_be_visible: bool, exit_on_close_request: bool, ) where A: Application + 'static, E: Executor + 'static, - C: Compositor + 'static, + C: Compositor, Renderer = A::Renderer> + 'static, ::Theme: StyleSheet, { use futures::stream::StreamExt; @@ -268,7 +272,7 @@ async fn run_instance( 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, ); @@ -608,7 +612,7 @@ pub fn update( messages: &mut Vec, window: &winit::window::Window, ) where - C: Compositor + 'static, + C: Compositor, Renderer = A::Renderer> + 'static, ::Theme: StyleSheet, { for message in messages.drain(..) { @@ -659,7 +663,7 @@ pub fn run_command( ) where A: Application, E: Executor, - C: Compositor + 'static, + C: Compositor, Renderer = A::Renderer> + 'static, ::Theme: StyleSheet, { use crate::runtime::command; 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); -- cgit From 8bf238697226e827dc983f9d89afbd0e252c5254 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 09:55:27 +0100 Subject: Remove `Compositor` window generic And update `glyphon` and `window_clipboard` --- Cargo.toml | 10 ++--- examples/custom_shader/src/scene/pipeline.rs | 2 + examples/integration/src/main.rs | 12 ++++-- futures/src/lib.rs | 4 +- futures/src/maybe.rs | 35 +++++++++++++++++ futures/src/maybe_send.rs | 21 ----------- graphics/Cargo.toml | 1 + graphics/src/compositor.rs | 23 ++++++++++-- graphics/src/lib.rs | 1 + renderer/Cargo.toml | 1 - renderer/src/compositor.rs | 36 +++++++----------- src/application.rs | 7 +--- tiny_skia/Cargo.toml | 1 - tiny_skia/src/window/compositor.rs | 56 ++++++++++++++-------------- wgpu/Cargo.toml | 1 - wgpu/src/window/compositor.rs | 40 +++++++------------- winit/src/application.rs | 8 ++-- winit/src/multi_window.rs | 14 ++++--- winit/src/multi_window/window_manager.rs | 7 ++-- 19 files changed, 146 insertions(+), 134 deletions(-) create mode 100644 futures/src/maybe.rs delete mode 100644 futures/src/maybe_send.rs diff --git a/Cargo.toml b/Cargo.toml index 421c7c76..131a4ef5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -128,10 +128,7 @@ bytemuck = { version = "1.0", features = ["derive"] } cosmic-text = "0.10" futures = "0.3" glam = "0.24" -# glyphon = "0.4" -# TODO update for wgpu 0.19 -# https://github.com/grovesNL/glyphon/pull/80 -glyphon = { git = "https://github.com/EggShark/glyphon" } +glyphon = "0.5" guillotiere = "0.6" half = "2.2" image = "0.24" @@ -165,6 +162,5 @@ web-sys = "0.3" web-time = "0.2" wgpu = "0.19" winapi = "0.3" -# window_clipboard = "0.3" -window_clipboard = { git = "https://github.com/ids1024/window_clipboard", branch = "raw-window-handle-0.6" } -winit = { git = "https://github.com/iced-rs/winit.git", rev = "b91e39ece2c0d378c3b80da7f3ab50e17bb798a5", features = ["rwh_06"] } +window_clipboard = "0.4" +winit = { git = "https://github.com/iced-rs/winit.git", rev = "b91e39ece2c0d378c3b80da7f3ab50e17bb798a5" } 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> { #[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> { 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> { .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> { 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> { 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..1a0bd1d1 --- /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 to write cross-platform async code! + pub trait MaybeSend: Send {} + + impl MaybeSend for T where T: Send {} + + /// An extension trait that enforces `Sync` only on native platforms. + /// + /// Useful to write cross-platform async code! + pub trait MaybeSync: Sync {} + + impl MaybeSync for T where T: Sync {} +} + +#[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 MaybeSend for T {} + + /// An extension trait that enforces `Send` only on native platforms. + /// + /// Useful to write cross-platform async code! + pub trait MaybeSync {} + + impl 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 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 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 6a4c7909..e6b9030b 100644 --- a/graphics/src/compositor.rs +++ b/graphics/src/compositor.rs @@ -2,13 +2,14 @@ //! surfaces. use crate::{Error, Viewport}; -use iced_core::Color; +use crate::core::Color; +use crate::futures::{MaybeSend, MaybeSync}; use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use thiserror::Error; /// A graphics compositor that can draw to windows. -pub trait Compositor: Sized { +pub trait Compositor: Sized { /// The settings of the backend. type Settings: Default; @@ -19,7 +20,7 @@ pub trait Compositor: Sized { type Surface; /// Creates a new [`Compositor`]. - fn new( + fn new( settings: Self::Settings, compatible_window: Option, ) -> Result; @@ -30,7 +31,7 @@ pub trait Compositor: Sized { /// Crates a new [`Surface`] for the given window. /// /// [`Surface`]: Self::Surface - fn create_surface( + fn create_surface( &mut self, window: W, width: u32, @@ -77,6 +78,20 @@ pub trait Compositor: Sized { ) -> Vec; } +/// 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 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 17157c66..a7c63444 100644 --- a/renderer/src/compositor.rs +++ b/renderer/src/compositor.rs @@ -1,36 +1,28 @@ 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::{HasDisplayHandle, HasWindowHandle}; use std::env; -pub enum Compositor { - TinySkia(iced_tiny_skia::window::Compositor), +pub enum Compositor { + TinySkia(iced_tiny_skia::window::Compositor), #[cfg(feature = "wgpu")] - Wgpu(iced_wgpu::window::Compositor), + Wgpu(iced_wgpu::window::Compositor), } -pub enum Surface { - TinySkia(iced_tiny_skia::window::Surface), +pub enum Surface { + TinySkia(iced_tiny_skia::window::Surface), #[cfg(feature = "wgpu")] Wgpu(iced_wgpu::window::Surface<'static>), } -// XXX Clone bound -// XXX Send/Sync? -// 'static? -impl< - W: Clone + Send + Sync + HasWindowHandle + HasDisplayHandle + 'static, - Theme, - > crate::graphics::Compositor for Compositor -{ +impl crate::graphics::Compositor for Compositor { type Settings = Settings; type Renderer = Renderer; - type Surface = Surface; + type Surface = Surface; - fn new( + fn new( settings: Self::Settings, compatible_window: Option, ) -> Result { @@ -63,12 +55,12 @@ impl< } } - fn create_surface( + fn create_surface( &mut self, window: W, width: u32, height: u32, - ) -> Surface { + ) -> Surface { match self { Self::TinySkia(compositor) => Surface::TinySkia( compositor.create_surface(window, width, height), @@ -82,7 +74,7 @@ impl< fn configure_surface( &mut self, - surface: &mut Surface, + surface: &mut Surface, width: u32, height: u32, ) { @@ -233,11 +225,11 @@ impl Candidate { ) } - fn build( + fn build( self, settings: Settings, _compatible_window: Option, - ) -> Result, Error> { + ) -> Result, Error> { match self { Self::TinySkia => { let compositor = iced_tiny_skia::window::compositor::new( diff --git a/src/application.rs b/src/application.rs index d7be6719..9518b8c5 100644 --- a/src/application.rs +++ b/src/application.rs @@ -1,8 +1,6 @@ //! Build interactive cross-platform applications. use crate::{Command, Element, Executor, Settings, Subscription}; -use std::sync::Arc; - pub use crate::style::application::{Appearance, StyleSheet}; /// An interactive cross-platform application. @@ -210,10 +208,7 @@ pub trait Application: Sized { Ok(crate::shell::application::run::< Instance, Self::Executor, - crate::renderer::Compositor< - Arc, - Self::Theme, - >, + crate::renderer::Compositor, >(settings.into(), renderer_settings)?) } } 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 788d7297..b5e9bcd8 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -4,34 +4,33 @@ use crate::graphics::damage; use crate::graphics::{Error, Viewport}; use crate::{Backend, Primitive, Renderer, Settings}; -use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use std::collections::VecDeque; use std::marker::PhantomData; use std::num::NonZeroU32; -pub struct Compositor { - context: Option>, +pub struct Compositor { + context: Option>>, settings: Settings, _theme: PhantomData, } -pub struct Surface { - window: softbuffer::Surface, +pub struct Surface { + window: softbuffer::Surface< + Box, + Box, + >, clip_mask: tiny_skia::Mask, // Primitives of existing buffers, by decreasing age primitives: VecDeque>, background_color: Color, } -// XXX avoid clone bound? -impl - crate::graphics::Compositor for Compositor -{ +impl crate::graphics::Compositor for Compositor { type Settings = Settings; type Renderer = Renderer; - type Surface = Surface; + type Surface = Surface; - fn new( + fn new( settings: Self::Settings, compatible_window: Option, ) -> Result { @@ -46,19 +45,21 @@ impl ) } - fn create_surface( + fn create_surface( &mut self, window: W, width: u32, height: u32, - ) -> Surface { + ) -> Surface { let window = if let Some(context) = self.context.as_ref() { - softbuffer::Surface::new(context, window) + softbuffer::Surface::new(context, Box::new(window.clone()) as _) .expect("Create softbuffer surface for window") } else { - let context = softbuffer::Context::new(window.clone()) - .expect("Create softbuffer context for window"); - softbuffer::Surface::new(&context, window) + let context = + softbuffer::Context::new(Box::new(window.clone()) as _) + .expect("Create softbuffer context for window"); + + softbuffer::Surface::new(&context, Box::new(window.clone()) as _) .expect("Create softbuffer surface for window") }; @@ -73,7 +74,7 @@ impl fn configure_surface( &mut self, - surface: &mut Surface, + surface: &mut Surface, width: u32, height: u32, ) { @@ -92,7 +93,7 @@ impl fn present>( &mut self, renderer: &mut Self::Renderer, - surface: &mut Surface, + surface: &mut Surface, viewport: &Viewport, background_color: Color, overlay: &[T], @@ -130,13 +131,14 @@ impl } } -pub fn new( +pub fn new( settings: Settings, compatible_window: Option, -) -> Compositor { +) -> Compositor { #[allow(unsafe_code)] - let context = - compatible_window.and_then(|w| softbuffer::Context::new(w).ok()); + let context = compatible_window + .and_then(|w| softbuffer::Context::new(Box::new(w) as _).ok()); + Compositor { context, settings, @@ -144,9 +146,9 @@ pub fn new( } } -pub fn present>( +pub fn present>( backend: &mut Backend, - surface: &mut Surface, + surface: &mut Surface, primitives: &[Primitive], viewport: &Viewport, background_color: Color, @@ -218,8 +220,8 @@ pub fn present>( buffer.present().map_err(|_| compositor::SurfaceError::Lost) } -pub fn screenshot>( - surface: &mut Surface, +pub fn screenshot>( + surface: &mut Surface, backend: &mut Backend, primitives: &[Primitive], viewport: &Viewport, 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 e2dc4901..0c063d0b 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -6,13 +6,11 @@ use crate::graphics::compositor; use crate::graphics::{Error, Viewport}; use crate::{Backend, Primitive, Renderer, Settings}; -use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; - use std::marker::PhantomData; /// A window graphics backend for iced powered by `wgpu`. #[allow(missing_debug_implementations)] -pub struct Compositor { +pub struct Compositor { settings: Settings, instance: wgpu::Instance, adapter: wgpu::Adapter, @@ -20,16 +18,13 @@ pub struct Compositor { queue: wgpu::Queue, format: wgpu::TextureFormat, theme: PhantomData, - w: PhantomData, } -impl - Compositor -{ +impl Compositor { /// Requests a new [`Compositor`] with the given [`Settings`]. /// /// Returns `None` if no compatible graphics adapter could be found. - pub async fn request( + pub async fn request( settings: Settings, compatible_window: Option, ) -> Option { @@ -45,7 +40,7 @@ impl let available_adapters: Vec<_> = instance .enumerate_adapters(settings.internal_backend) .iter() - .map(|adapter| adapter.get_info()) + .map(wgpu::Adapter::get_info) .collect(); log::info!("Available adapters: {available_adapters:#?}"); } @@ -129,7 +124,6 @@ impl queue, format, theme: PhantomData, - w: PhantomData, }) } @@ -141,13 +135,10 @@ impl /// Creates a [`Compositor`] and its [`Backend`] for the given [`Settings`] and /// window. -pub fn new< - Theme, - W: HasWindowHandle + HasDisplayHandle + wgpu::WasmNotSendSync, ->( +pub fn new( settings: Settings, compatible_window: Option, -) -> Result, Error> { +) -> Result, Error> { let compositor = futures::executor::block_on(Compositor::request( settings, compatible_window, @@ -158,8 +149,8 @@ pub fn new< } /// Presents the given primitives with the given [`Compositor`] and [`Backend`]. -pub fn present>( - compositor: &mut Compositor, +pub fn present>( + compositor: &mut Compositor, backend: &mut Backend, surface: &mut wgpu::Surface<'static>, primitives: &[Primitive], @@ -212,17 +203,12 @@ pub fn present>( } } -impl< - W: HasDisplayHandle + HasWindowHandle + wgpu::WasmNotSendSync + 'static, - Theme, - > graphics::Compositor for Compositor -{ +impl graphics::Compositor for Compositor { type Settings = Settings; type Renderer = Renderer; - // XXX generic instead of 'static type Surface = wgpu::Surface<'static>; - fn new( + fn new( settings: Self::Settings, compatible_window: Option, ) -> Result { @@ -237,7 +223,7 @@ impl< ) } - fn create_surface( + fn create_surface( &mut self, window: W, width: u32, @@ -328,8 +314,8 @@ impl< /// Renders the current surface to an offscreen buffer. /// /// Returns RGBA bytes of the texture data. -pub fn screenshot>( - compositor: &Compositor, +pub fn screenshot>( + compositor: &Compositor, backend: &mut Backend, primitives: &[Primitive], viewport: &Viewport, diff --git a/winit/src/application.rs b/winit/src/application.rs index d639a36b..c5e11167 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -106,7 +106,7 @@ pub fn run( where A: Application + 'static, E: Executor + 'static, - C: Compositor, Renderer = A::Renderer> + 'static, + C: Compositor + 'static, ::Theme: StyleSheet, { use futures::task; @@ -258,7 +258,7 @@ async fn run_instance( ) where A: Application + 'static, E: Executor + 'static, - C: Compositor, Renderer = A::Renderer> + 'static, + C: Compositor + 'static, ::Theme: StyleSheet, { use futures::stream::StreamExt; @@ -612,7 +612,7 @@ pub fn update( messages: &mut Vec, window: &winit::window::Window, ) where - C: Compositor, Renderer = A::Renderer> + 'static, + C: Compositor + 'static, ::Theme: StyleSheet, { for message in messages.drain(..) { @@ -663,7 +663,7 @@ pub fn run_command( ) where A: Application, E: Executor, - C: Compositor, Renderer = A::Renderer> + 'static, + C: Compositor + 'static, ::Theme: StyleSheet, { use crate::runtime::command; diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs index 84c81bea..21196460 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,8 @@ where }; } - let mut compositor = C::new(compositor_settings, Some(&main_window))?; + let mut compositor = + C::new(compositor_settings, Some(main_window.clone()))?; let mut window_manager = WindowManager::new(); let _ = window_manager.insert( @@ -388,7 +392,7 @@ async fn run_instance( } => { 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, 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, ::Theme: StyleSheet, { - pub raw: winit::window::Window, + pub raw: Arc, pub state: State, pub viewport_version: u64, pub exit_on_close_request: bool, -- cgit From b9dc106a56a9f91673f3a64b05e8413150adf5e0 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 09:58:54 +0100 Subject: Remove `winit` dependency from `iced` root crate --- Cargo.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 131a4ef5..665dc5a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,8 +70,6 @@ thiserror.workspace = true image.workspace = true image.optional = true -winit.workspace = true - [profile.release-opt] inherits = "release" codegen-units = 1 -- cgit From 4c90ed6a1b50331d889d79aacbf653fc6d98950f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 09:59:36 +0100 Subject: Remove patch version from `softbuffer` --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 665dc5a1..c9dee6b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -145,7 +145,7 @@ resvg = "0.36" rustc-hash = "1.0" smol = "1.0" smol_str = "0.2" -softbuffer = "0.4.1" +softbuffer = "0.4" syntect = "5.1" sysinfo = "0.28" thiserror = "1.0" -- cgit From 1701ec815d3f25ea8097e806081e7a3ac9ba4d82 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:02:50 +0100 Subject: Remove redundant `ref mut` in `iced_renderer::compositor` --- renderer/src/compositor.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/renderer/src/compositor.rs b/renderer/src/compositor.rs index a7c63444..0b56f101 100644 --- a/renderer/src/compositor.rs +++ b/renderer/src/compositor.rs @@ -113,7 +113,7 @@ impl crate::graphics::Compositor for Compositor { ( Self::TinySkia(_compositor), crate::Renderer::TinySkia(renderer), - Surface::TinySkia(ref mut surface), + Surface::TinySkia(surface), ) => renderer.with_primitives(|backend, primitives| { iced_tiny_skia::window::compositor::present( backend, @@ -128,7 +128,7 @@ impl crate::graphics::Compositor for Compositor { ( Self::Wgpu(compositor), crate::Renderer::Wgpu(renderer), - Surface::Wgpu(ref mut surface), + Surface::Wgpu(surface), ) => renderer.with_primitives(|backend, primitives| { iced_wgpu::window::compositor::present( compositor, @@ -160,7 +160,7 @@ impl crate::graphics::Compositor for Compositor { ( Self::TinySkia(_compositor), Renderer::TinySkia(renderer), - Surface::TinySkia(ref mut surface), + Surface::TinySkia(surface), ) => renderer.with_primitives(|backend, primitives| { iced_tiny_skia::window::compositor::screenshot( surface, -- cgit From 5fc49edc55a0e64c4c46ca55eddafe9d4e8232e1 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:06:30 +0100 Subject: Make `compatible_window` mandatory in `Compositor` --- graphics/src/compositor.rs | 2 +- renderer/src/compositor.rs | 4 ++-- tiny_skia/src/window/compositor.rs | 26 ++++++++++---------------- wgpu/src/window/compositor.rs | 6 +++--- winit/src/application.rs | 2 +- winit/src/multi_window.rs | 3 +-- 6 files changed, 18 insertions(+), 25 deletions(-) diff --git a/graphics/src/compositor.rs b/graphics/src/compositor.rs index e6b9030b..0188f4d8 100644 --- a/graphics/src/compositor.rs +++ b/graphics/src/compositor.rs @@ -22,7 +22,7 @@ pub trait Compositor: Sized { /// Creates a new [`Compositor`]. fn new( settings: Self::Settings, - compatible_window: Option, + compatible_window: W, ) -> Result; /// Creates a [`Self::Renderer`] for the [`Compositor`]. diff --git a/renderer/src/compositor.rs b/renderer/src/compositor.rs index 0b56f101..f10ed048 100644 --- a/renderer/src/compositor.rs +++ b/renderer/src/compositor.rs @@ -24,7 +24,7 @@ impl crate::graphics::Compositor for Compositor { fn new( settings: Self::Settings, - compatible_window: Option, + compatible_window: W, ) -> Result { let candidates = Candidate::list_from_env().unwrap_or(Candidate::default_list()); @@ -228,7 +228,7 @@ impl Candidate { fn build( self, settings: Settings, - _compatible_window: Option, + _compatible_window: W, ) -> Result, Error> { match self { Self::TinySkia => { diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index b5e9bcd8..86400aa0 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -9,7 +9,7 @@ use std::marker::PhantomData; use std::num::NonZeroU32; pub struct Compositor { - context: Option>>, + context: softbuffer::Context>, settings: Settings, _theme: PhantomData, } @@ -32,7 +32,7 @@ impl crate::graphics::Compositor for Compositor { fn new( settings: Self::Settings, - compatible_window: Option, + compatible_window: W, ) -> Result { Ok(new(settings, compatible_window)) } @@ -51,17 +51,11 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) -> Surface { - let window = if let Some(context) = self.context.as_ref() { - softbuffer::Surface::new(context, Box::new(window.clone()) as _) - .expect("Create softbuffer surface for window") - } else { - let context = - softbuffer::Context::new(Box::new(window.clone()) as _) - .expect("Create softbuffer context for window"); - - softbuffer::Surface::new(&context, Box::new(window.clone()) as _) - .expect("Create softbuffer surface for window") - }; + let window = softbuffer::Surface::new( + &self.context, + Box::new(window.clone()) as _, + ) + .expect("Create softbuffer surface for window"); Surface { window, @@ -133,11 +127,11 @@ impl crate::graphics::Compositor for Compositor { pub fn new( settings: Settings, - compatible_window: Option, + compatible_window: W, ) -> Compositor { #[allow(unsafe_code)] - let context = compatible_window - .and_then(|w| softbuffer::Context::new(Box::new(w) as _).ok()); + let context = softbuffer::Context::new(Box::new(compatible_window) as _) + .expect("Create softbuffer context"); Compositor { context, diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index 0c063d0b..105d83a8 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -137,11 +137,11 @@ impl Compositor { /// window. pub fn new( settings: Settings, - compatible_window: Option, + compatible_window: W, ) -> Result, Error> { let compositor = futures::executor::block_on(Compositor::request( settings, - compatible_window, + Some(compatible_window), )) .ok_or(Error::GraphicsAdapterNotFound)?; @@ -210,7 +210,7 @@ impl graphics::Compositor for Compositor { fn new( settings: Self::Settings, - compatible_window: Option, + compatible_window: W, ) -> Result { new(settings, compatible_window) } diff --git a/winit/src/application.rs b/winit/src/application.rs index c5e11167..5fcdbbd8 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -187,7 +187,7 @@ where }; } - let compositor = C::new(compositor_settings, Some(window.clone()))?; + let compositor = C::new(compositor_settings, window.clone())?; let mut renderer = compositor.create_renderer(); for font in settings.fonts { diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs index 21196460..3f0ba056 100644 --- a/winit/src/multi_window.rs +++ b/winit/src/multi_window.rs @@ -187,8 +187,7 @@ where }; } - let mut compositor = - C::new(compositor_settings, Some(main_window.clone()))?; + let mut compositor = C::new(compositor_settings, main_window.clone())?; let mut window_manager = WindowManager::new(); let _ = window_manager.insert( -- cgit From 4b7744b9806397c9891b1fc179df8a61eaa3670d Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:35:27 +0100 Subject: Support out-of-order `Buffer` ages in `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 86400aa0..c0aabdb6 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -20,9 +20,9 @@ pub struct Surface { Box, >, clip_mask: tiny_skia::Mask, - // Primitives of existing buffers, by decreasing age - primitives: VecDeque>, + primitive_stack: VecDeque>, background_color: Color, + max_age: u8, } impl crate::graphics::Compositor for Compositor { @@ -61,8 +61,9 @@ impl crate::graphics::Compositor for Compositor { window, clip_mask: tiny_skia::Mask::new(width, height) .expect("Create clip mask"), - primitives: VecDeque::new(), + primitive_stack: VecDeque::new(), background_color: Color::BLACK, + max_age: 0, } } @@ -74,7 +75,7 @@ impl crate::graphics::Compositor for Compositor { ) { surface.clip_mask = tiny_skia::Mask::new(width, height).expect("Create clip mask"); - surface.primitives.clear(); + surface.primitive_stack.clear(); } fn fetch_information(&self) -> Information { @@ -159,7 +160,6 @@ pub fn present>( ) .unwrap(); - // TODO Add variants to `SurfaceError`? let mut buffer = surface .window .buffer_mut() @@ -167,27 +167,25 @@ pub fn present>( let age = buffer.age(); - // Forget primatives for back buffers older than `age` - // Or if this is a new buffer, keep at most two. - let max = if age == 0 { 2 } else { age }; - while surface.primitives.len() as u8 > max { - let _ = surface.primitives.pop_front(); - } + let last_primitives = { + surface.max_age = surface.max_age.max(age); + surface.primitive_stack.truncate(surface.max_age as usize); - let last_primitives = if surface.primitives.len() as u8 == age { - surface.primitives.pop_front() - } else { - None + 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)) + .then(|| damage::list(last_primitives, primitives)) }) .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); - surface.primitives.push_back(primitives.to_vec()); + surface.primitive_stack.push_front(primitives.to_vec()); surface.background_color = background_color; if !damage.is_empty() { -- cgit From b6b3e9b9f995abf5cc65814e143418b6f1ec7464 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:42:02 +0100 Subject: Avoid stacking new primitives when undamaged --- tiny_skia/src/window/compositor.rs | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index c0aabdb6..dae57975 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -185,29 +185,31 @@ pub fn present>( }) .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); + if damage.is_empty() { + return Ok(()); + } + surface.primitive_stack.push_front(primitives.to_vec()); surface.background_color = background_color; - if !damage.is_empty() { - let damage = damage::group(damage, scale_factor, physical_size); + 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, - primitives, - viewport, - &damage, - background_color, - overlay, - ); - } + 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, + primitives, + viewport, + &damage, + background_color, + overlay, + ); buffer.present().map_err(|_| compositor::SurfaceError::Lost) } -- cgit From 150ce65e209414847ae133a70c833addd3086e15 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:43:52 +0100 Subject: Nest `age` declaration inside `last_primitives` --- tiny_skia/src/window/compositor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index dae57975..08a49bc5 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -165,9 +165,9 @@ pub fn present>( .buffer_mut() .map_err(|_| compositor::SurfaceError::Lost)?; - let age = buffer.age(); - let last_primitives = { + let age = buffer.age(); + surface.max_age = surface.max_age.max(age); surface.primitive_stack.truncate(surface.max_age as usize); -- cgit From 3cf8f77d6537f9d864f4a554b2fff46676a761f6 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:52:25 +0100 Subject: Resize surface in `configure_surface` in `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 08a49bc5..17d21100 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -57,14 +57,18 @@ impl crate::graphics::Compositor for Compositor { ) .expect("Create softbuffer surface for window"); - Surface { + let mut surface = Surface { window, clip_mask: tiny_skia::Mask::new(width, height) .expect("Create clip mask"), primitive_stack: VecDeque::new(), background_color: Color::BLACK, max_age: 0, - } + }; + + self.configure_surface(&mut surface, width, height); + + surface } fn configure_surface( @@ -73,6 +77,14 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) { + 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.primitive_stack.clear(); @@ -152,14 +164,6 @@ pub fn present>( let physical_size = viewport.physical_size(); let scale_factor = viewport.scale_factor() as f32; - surface - .window - .resize( - NonZeroU32::new(physical_size.width).unwrap(), - NonZeroU32::new(physical_size.height).unwrap(), - ) - .unwrap(); - let mut buffer = surface .window .buffer_mut() -- cgit From c929e6f5dd30044df4e7400ab633eaf0a53ce3dd Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:56:02 +0100 Subject: Use `Self::Surface` in `Compositor` implementors --- tiny_skia/src/window/compositor.rs | 6 +++--- wgpu/src/window/compositor.rs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 17d21100..781ed8a5 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -50,7 +50,7 @@ impl crate::graphics::Compositor for Compositor { window: W, width: u32, height: u32, - ) -> Surface { + ) -> Self::Surface { let window = softbuffer::Surface::new( &self.context, Box::new(window.clone()) as _, @@ -73,7 +73,7 @@ impl crate::graphics::Compositor for Compositor { fn configure_surface( &mut self, - surface: &mut Surface, + surface: &mut Self::Surface, width: u32, height: u32, ) { @@ -100,7 +100,7 @@ impl crate::graphics::Compositor for Compositor { fn present>( &mut self, renderer: &mut Self::Renderer, - surface: &mut Surface, + surface: &mut Self::Surface, viewport: &Viewport, background_color: Color, overlay: &[T], diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index 105d83a8..31cf3819 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -228,7 +228,7 @@ impl graphics::Compositor for Compositor { window: W, width: u32, height: u32, - ) -> wgpu::Surface<'static> { + ) -> Self::Surface { let mut surface = self .instance .create_surface(window) @@ -241,7 +241,7 @@ impl graphics::Compositor for Compositor { fn configure_surface( &mut self, - surface: &mut wgpu::Surface<'static>, + surface: &mut Self::Surface, width: u32, height: u32, ) { @@ -272,7 +272,7 @@ impl graphics::Compositor for Compositor { fn present>( &mut self, renderer: &mut Self::Renderer, - surface: &mut wgpu::Surface<'static>, + surface: &mut Self::Surface, viewport: &Viewport, background_color: Color, overlay: &[T], @@ -293,7 +293,7 @@ impl graphics::Compositor for Compositor { fn screenshot>( &mut self, renderer: &mut Self::Renderer, - _surface: &mut wgpu::Surface<'static>, + _surface: &mut Self::Surface, viewport: &Viewport, background_color: Color, overlay: &[T], -- cgit From 74a6e58cbc3354d45ed6cd86e58c624a946d0f05 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:57:53 +0100 Subject: Remove comment in `iced_winit::application` --- winit/src/application.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/winit/src/application.rs b/winit/src/application.rs index 5fcdbbd8..09bf63cc 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -150,7 +150,6 @@ where log::debug!("Window builder: {builder:#?}"); - // XXX Arc? let window = Arc::new( builder .build(&event_loop) -- cgit From cba56ea76821a3204923d34c3fe634730a86f22d Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 11:02:53 +0100 Subject: Fix typo `Send -> Sync` --- futures/src/maybe.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/futures/src/maybe.rs b/futures/src/maybe.rs index 1a0bd1d1..c564a739 100644 --- a/futures/src/maybe.rs +++ b/futures/src/maybe.rs @@ -24,7 +24,7 @@ mod platform { impl MaybeSend for T {} - /// An extension trait that enforces `Send` only on native platforms. + /// An extension trait that enforces `Sync` only on native platforms. /// /// Useful to write cross-platform async code! pub trait MaybeSync {} -- cgit From bdb8f4966ea75c0147165541771ed3f952ac8d13 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 11:21:41 +0100 Subject: Fix grammar in `iced_futures::maybe` module --- futures/src/maybe.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/futures/src/maybe.rs b/futures/src/maybe.rs index c564a739..c6a507c1 100644 --- a/futures/src/maybe.rs +++ b/futures/src/maybe.rs @@ -2,14 +2,14 @@ mod platform { /// An extension trait that enforces `Send` only on native platforms. /// - /// Useful to write cross-platform async code! + /// Useful for writing cross-platform async code! pub trait MaybeSend: Send {} impl MaybeSend for T where T: Send {} /// An extension trait that enforces `Sync` only on native platforms. /// - /// Useful to write cross-platform async code! + /// Useful for writing cross-platform async code! pub trait MaybeSync: Sync {} impl MaybeSync for T where T: Sync {} @@ -19,14 +19,14 @@ mod platform { mod platform { /// An extension trait that enforces `Send` only on native platforms. /// - /// Useful to write cross-platform async code! + /// Useful for writing cross-platform async code! pub trait MaybeSend {} impl MaybeSend for T {} /// An extension trait that enforces `Sync` only on native platforms. /// - /// Useful to write cross-platform async code! + /// Useful for writing cross-platform async code! pub trait MaybeSync {} impl MaybeSync for T {} -- cgit From 9df7bf8ec30ca76016018bc758b4323760e231b0 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 15:41:19 +0100 Subject: Use `workspace` dependency for `raw-window-handle` in `iced_core` --- core/Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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" -- cgit