WIP raw-window-handle 0.6
This commit is contained in:
parent
ff268c8c42
commit
7289b6091b
8 changed files with 142 additions and 102 deletions
18
Cargo.toml
18
Cargo.toml
|
|
@ -70,6 +70,8 @@ thiserror.workspace = true
|
||||||
image.workspace = true
|
image.workspace = true
|
||||||
image.optional = true
|
image.optional = true
|
||||||
|
|
||||||
|
winit.workspace = true
|
||||||
|
|
||||||
[profile.release-opt]
|
[profile.release-opt]
|
||||||
inherits = "release"
|
inherits = "release"
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
@ -126,7 +128,10 @@ bytemuck = { version = "1.0", features = ["derive"] }
|
||||||
cosmic-text = "0.10"
|
cosmic-text = "0.10"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
glam = "0.24"
|
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"
|
guillotiere = "0.6"
|
||||||
half = "2.2"
|
half = "2.2"
|
||||||
image = "0.24"
|
image = "0.24"
|
||||||
|
|
@ -140,12 +145,12 @@ once_cell = "1.0"
|
||||||
ouroboros = "0.17"
|
ouroboros = "0.17"
|
||||||
palette = "0.7"
|
palette = "0.7"
|
||||||
qrcode = { version = "0.12", default-features = false }
|
qrcode = { version = "0.12", default-features = false }
|
||||||
raw-window-handle = "0.5"
|
raw-window-handle = "0.6"
|
||||||
resvg = "0.36"
|
resvg = "0.36"
|
||||||
rustc-hash = "1.0"
|
rustc-hash = "1.0"
|
||||||
smol = "1.0"
|
smol = "1.0"
|
||||||
smol_str = "0.2"
|
smol_str = "0.2"
|
||||||
softbuffer = "0.3.4"
|
softbuffer = "0.4.1"
|
||||||
syntect = "5.1"
|
syntect = "5.1"
|
||||||
sysinfo = "0.28"
|
sysinfo = "0.28"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
@ -158,7 +163,8 @@ wasm-bindgen-futures = "0.4"
|
||||||
wasm-timer = "0.2"
|
wasm-timer = "0.2"
|
||||||
web-sys = "0.3"
|
web-sys = "0.3"
|
||||||
web-time = "0.2"
|
web-time = "0.2"
|
||||||
wgpu = "0.18"
|
wgpu = "0.19"
|
||||||
winapi = "0.3"
|
winapi = "0.3"
|
||||||
window_clipboard = "0.3"
|
# window_clipboard = "0.3"
|
||||||
winit = { git = "https://github.com/iced-rs/winit.git", rev = "b91e39ece2c0d378c3b80da7f3ab50e17bb798a5", features = ["rwh_05"] }
|
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"] }
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ use crate::{Error, Viewport};
|
||||||
|
|
||||||
use iced_core::Color;
|
use iced_core::Color;
|
||||||
|
|
||||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
/// A graphics compositor that can draw to windows.
|
/// A graphics compositor that can draw to windows.
|
||||||
pub trait Compositor: Sized {
|
pub trait Compositor<W: HasWindowHandle + HasDisplayHandle>: Sized {
|
||||||
/// The settings of the backend.
|
/// The settings of the backend.
|
||||||
type Settings: Default;
|
type Settings: Default;
|
||||||
|
|
||||||
|
|
@ -19,9 +19,9 @@ pub trait Compositor: Sized {
|
||||||
type Surface;
|
type Surface;
|
||||||
|
|
||||||
/// Creates a new [`Compositor`].
|
/// Creates a new [`Compositor`].
|
||||||
fn new<W: HasRawWindowHandle + HasRawDisplayHandle>(
|
fn new(
|
||||||
settings: Self::Settings,
|
settings: Self::Settings,
|
||||||
compatible_window: Option<&W>,
|
compatible_window: Option<W>,
|
||||||
) -> Result<Self, Error>;
|
) -> Result<Self, Error>;
|
||||||
|
|
||||||
/// Creates a [`Self::Renderer`] for the [`Compositor`].
|
/// Creates a [`Self::Renderer`] for the [`Compositor`].
|
||||||
|
|
@ -30,9 +30,9 @@ pub trait Compositor: Sized {
|
||||||
/// Crates a new [`Surface`] for the given window.
|
/// Crates a new [`Surface`] for the given window.
|
||||||
///
|
///
|
||||||
/// [`Surface`]: Self::Surface
|
/// [`Surface`]: Self::Surface
|
||||||
fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>(
|
fn create_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
window: &W,
|
window: W,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> Self::Surface;
|
) -> Self::Surface;
|
||||||
|
|
|
||||||
|
|
@ -3,29 +3,36 @@ use crate::graphics::compositor::{Information, SurfaceError};
|
||||||
use crate::graphics::{Error, Viewport};
|
use crate::graphics::{Error, Viewport};
|
||||||
use crate::{Renderer, Settings};
|
use crate::{Renderer, Settings};
|
||||||
|
|
||||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
pub enum Compositor<Theme> {
|
pub enum Compositor<W: HasWindowHandle + HasDisplayHandle, Theme> {
|
||||||
TinySkia(iced_tiny_skia::window::Compositor<Theme>),
|
TinySkia(iced_tiny_skia::window::Compositor<W, Theme>),
|
||||||
#[cfg(feature = "wgpu")]
|
#[cfg(feature = "wgpu")]
|
||||||
Wgpu(iced_wgpu::window::Compositor<Theme>),
|
Wgpu(iced_wgpu::window::Compositor<W, Theme>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Surface {
|
pub enum Surface<W: HasWindowHandle + HasDisplayHandle> {
|
||||||
TinySkia(iced_tiny_skia::window::Surface),
|
TinySkia(iced_tiny_skia::window::Surface<W>),
|
||||||
#[cfg(feature = "wgpu")]
|
#[cfg(feature = "wgpu")]
|
||||||
Wgpu(iced_wgpu::window::Surface),
|
Wgpu(iced_wgpu::window::Surface<'static>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
// XXX Clone bound
|
||||||
|
// XXX Send/Sync?
|
||||||
|
// 'static?
|
||||||
|
impl<
|
||||||
|
W: Clone + Send + Sync + HasWindowHandle + HasDisplayHandle + 'static,
|
||||||
|
Theme,
|
||||||
|
> crate::graphics::Compositor<W> for Compositor<W, Theme>
|
||||||
|
{
|
||||||
type Settings = Settings;
|
type Settings = Settings;
|
||||||
type Renderer = Renderer<Theme>;
|
type Renderer = Renderer<Theme>;
|
||||||
type Surface = Surface;
|
type Surface = Surface<W>;
|
||||||
|
|
||||||
fn new<W: HasRawWindowHandle + HasRawDisplayHandle>(
|
fn new(
|
||||||
settings: Self::Settings,
|
settings: Self::Settings,
|
||||||
compatible_window: Option<&W>,
|
compatible_window: Option<W>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let candidates =
|
let candidates =
|
||||||
Candidate::list_from_env().unwrap_or(Candidate::default_list());
|
Candidate::list_from_env().unwrap_or(Candidate::default_list());
|
||||||
|
|
@ -33,7 +40,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
let mut error = Error::GraphicsAdapterNotFound;
|
let mut error = Error::GraphicsAdapterNotFound;
|
||||||
|
|
||||||
for candidate in candidates {
|
for candidate in candidates {
|
||||||
match candidate.build(settings, compatible_window) {
|
match candidate.build(settings, compatible_window.clone()) {
|
||||||
Ok(compositor) => return Ok(compositor),
|
Ok(compositor) => return Ok(compositor),
|
||||||
Err(new_error) => {
|
Err(new_error) => {
|
||||||
error = new_error;
|
error = new_error;
|
||||||
|
|
@ -56,12 +63,12 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>(
|
fn create_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
window: &W,
|
window: W,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> Surface {
|
) -> Surface<W> {
|
||||||
match self {
|
match self {
|
||||||
Self::TinySkia(compositor) => Surface::TinySkia(
|
Self::TinySkia(compositor) => Surface::TinySkia(
|
||||||
compositor.create_surface(window, width, height),
|
compositor.create_surface(window, width, height),
|
||||||
|
|
@ -75,7 +82,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
|
|
||||||
fn configure_surface(
|
fn configure_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
surface: &mut Surface,
|
surface: &mut Surface<W>,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
) {
|
) {
|
||||||
|
|
@ -114,7 +121,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
(
|
(
|
||||||
Self::TinySkia(_compositor),
|
Self::TinySkia(_compositor),
|
||||||
crate::Renderer::TinySkia(renderer),
|
crate::Renderer::TinySkia(renderer),
|
||||||
Surface::TinySkia(surface),
|
Surface::TinySkia(ref mut surface),
|
||||||
) => renderer.with_primitives(|backend, primitives| {
|
) => renderer.with_primitives(|backend, primitives| {
|
||||||
iced_tiny_skia::window::compositor::present(
|
iced_tiny_skia::window::compositor::present(
|
||||||
backend,
|
backend,
|
||||||
|
|
@ -129,7 +136,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
(
|
(
|
||||||
Self::Wgpu(compositor),
|
Self::Wgpu(compositor),
|
||||||
crate::Renderer::Wgpu(renderer),
|
crate::Renderer::Wgpu(renderer),
|
||||||
Surface::Wgpu(surface),
|
Surface::Wgpu(ref mut surface),
|
||||||
) => renderer.with_primitives(|backend, primitives| {
|
) => renderer.with_primitives(|backend, primitives| {
|
||||||
iced_wgpu::window::compositor::present(
|
iced_wgpu::window::compositor::present(
|
||||||
compositor,
|
compositor,
|
||||||
|
|
@ -161,7 +168,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
(
|
(
|
||||||
Self::TinySkia(_compositor),
|
Self::TinySkia(_compositor),
|
||||||
Renderer::TinySkia(renderer),
|
Renderer::TinySkia(renderer),
|
||||||
Surface::TinySkia(surface),
|
Surface::TinySkia(ref mut surface),
|
||||||
) => renderer.with_primitives(|backend, primitives| {
|
) => renderer.with_primitives(|backend, primitives| {
|
||||||
iced_tiny_skia::window::compositor::screenshot(
|
iced_tiny_skia::window::compositor::screenshot(
|
||||||
surface,
|
surface,
|
||||||
|
|
@ -226,11 +233,11 @@ impl Candidate {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build<Theme, W: HasRawWindowHandle + HasRawDisplayHandle>(
|
fn build<Theme, W: HasWindowHandle + HasDisplayHandle + Send + Sync>(
|
||||||
self,
|
self,
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
_compatible_window: Option<&W>,
|
_compatible_window: Option<W>,
|
||||||
) -> Result<Compositor<Theme>, Error> {
|
) -> Result<Compositor<W, Theme>, Error> {
|
||||||
match self {
|
match self {
|
||||||
Self::TinySkia => {
|
Self::TinySkia => {
|
||||||
let compositor = iced_tiny_skia::window::compositor::new(
|
let compositor = iced_tiny_skia::window::compositor::new(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
//! Build interactive cross-platform applications.
|
//! Build interactive cross-platform applications.
|
||||||
use crate::{Command, Element, Executor, Settings, Subscription};
|
use crate::{Command, Element, Executor, Settings, Subscription};
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub use crate::style::application::{Appearance, StyleSheet};
|
pub use crate::style::application::{Appearance, StyleSheet};
|
||||||
|
|
||||||
/// An interactive cross-platform application.
|
/// An interactive cross-platform application.
|
||||||
|
|
@ -208,7 +210,10 @@ pub trait Application: Sized {
|
||||||
Ok(crate::shell::application::run::<
|
Ok(crate::shell::application::run::<
|
||||||
Instance<Self>,
|
Instance<Self>,
|
||||||
Self::Executor,
|
Self::Executor,
|
||||||
crate::renderer::Compositor<Self::Theme>,
|
crate::renderer::Compositor<
|
||||||
|
Arc<winit::window::Window>,
|
||||||
|
Self::Theme,
|
||||||
|
>,
|
||||||
>(settings.into(), renderer_settings)?)
|
>(settings.into(), renderer_settings)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,33 +4,36 @@ use crate::graphics::damage;
|
||||||
use crate::graphics::{Error, Viewport};
|
use crate::graphics::{Error, Viewport};
|
||||||
use crate::{Backend, Primitive, Renderer, Settings};
|
use crate::{Backend, Primitive, Renderer, Settings};
|
||||||
|
|
||||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
pub struct Compositor<Theme> {
|
pub struct Compositor<W: HasDisplayHandle + HasWindowHandle, Theme> {
|
||||||
context: Option<softbuffer::Context>,
|
context: Option<softbuffer::Context<W>>,
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
_theme: PhantomData<Theme>,
|
_theme: PhantomData<Theme>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Surface {
|
pub struct Surface<W: HasDisplayHandle + HasWindowHandle> {
|
||||||
window: softbuffer::Surface,
|
window: softbuffer::Surface<W, W>,
|
||||||
clip_mask: tiny_skia::Mask,
|
clip_mask: tiny_skia::Mask,
|
||||||
// Primitives of existing buffers, by decreasing age
|
// Primitives of existing buffers, by decreasing age
|
||||||
primitives: VecDeque<Vec<Primitive>>,
|
primitives: VecDeque<Vec<Primitive>>,
|
||||||
background_color: Color,
|
background_color: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
// XXX avoid clone bound?
|
||||||
|
impl<W: HasDisplayHandle + HasWindowHandle + Clone, Theme>
|
||||||
|
crate::graphics::Compositor<W> for Compositor<W, Theme>
|
||||||
|
{
|
||||||
type Settings = Settings;
|
type Settings = Settings;
|
||||||
type Renderer = Renderer<Theme>;
|
type Renderer = Renderer<Theme>;
|
||||||
type Surface = Surface;
|
type Surface = Surface<W>;
|
||||||
|
|
||||||
fn new<W: HasRawWindowHandle + HasRawDisplayHandle>(
|
fn new(
|
||||||
settings: Self::Settings,
|
settings: Self::Settings,
|
||||||
compatible_window: Option<&W>,
|
compatible_window: Option<W>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
Ok(new(settings, compatible_window))
|
Ok(new(settings, compatible_window))
|
||||||
}
|
}
|
||||||
|
|
@ -43,20 +46,19 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>(
|
fn create_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
window: &W,
|
window: W,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> Surface {
|
) -> Surface<W> {
|
||||||
#[allow(unsafe_code)]
|
|
||||||
let window = if let Some(context) = self.context.as_ref() {
|
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")
|
.expect("Create softbuffer surface for window")
|
||||||
} else {
|
} else {
|
||||||
let context = unsafe { softbuffer::Context::new(window) }
|
let context = softbuffer::Context::new(window.clone())
|
||||||
.expect("Create softbuffer context for window");
|
.expect("Create softbuffer context for window");
|
||||||
unsafe { softbuffer::Surface::new(&context, window) }
|
softbuffer::Surface::new(&context, window)
|
||||||
.expect("Create softbuffer surface for window")
|
.expect("Create softbuffer surface for window")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -71,7 +73,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
|
|
||||||
fn configure_surface(
|
fn configure_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
surface: &mut Surface,
|
surface: &mut Surface<W>,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
) {
|
) {
|
||||||
|
|
@ -90,7 +92,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
fn present<T: AsRef<str>>(
|
fn present<T: AsRef<str>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
renderer: &mut Self::Renderer,
|
renderer: &mut Self::Renderer,
|
||||||
surface: &mut Self::Surface,
|
surface: &mut Surface<W>,
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
background_color: Color,
|
background_color: Color,
|
||||||
overlay: &[T],
|
overlay: &[T],
|
||||||
|
|
@ -128,13 +130,13 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new<W: HasRawWindowHandle + HasRawDisplayHandle, Theme>(
|
pub fn new<W: HasWindowHandle + HasDisplayHandle, Theme>(
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
compatible_window: Option<&W>,
|
compatible_window: Option<W>,
|
||||||
) -> Compositor<Theme> {
|
) -> Compositor<W, Theme> {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
let context = compatible_window
|
let context =
|
||||||
.and_then(|w| unsafe { softbuffer::Context::new(w) }.ok());
|
compatible_window.and_then(|w| softbuffer::Context::new(w).ok());
|
||||||
Compositor {
|
Compositor {
|
||||||
context,
|
context,
|
||||||
settings,
|
settings,
|
||||||
|
|
@ -142,9 +144,9 @@ pub fn new<W: HasRawWindowHandle + HasRawDisplayHandle, Theme>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn present<T: AsRef<str>>(
|
pub fn present<W: HasDisplayHandle + HasWindowHandle, T: AsRef<str>>(
|
||||||
backend: &mut Backend,
|
backend: &mut Backend,
|
||||||
surface: &mut Surface,
|
surface: &mut Surface<W>,
|
||||||
primitives: &[Primitive],
|
primitives: &[Primitive],
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
background_color: Color,
|
background_color: Color,
|
||||||
|
|
@ -216,8 +218,8 @@ pub fn present<T: AsRef<str>>(
|
||||||
buffer.present().map_err(|_| compositor::SurfaceError::Lost)
|
buffer.present().map_err(|_| compositor::SurfaceError::Lost)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn screenshot<T: AsRef<str>>(
|
pub fn screenshot<W: HasDisplayHandle + HasWindowHandle, T: AsRef<str>>(
|
||||||
surface: &mut Surface,
|
surface: &mut Surface<W>,
|
||||||
backend: &mut Backend,
|
backend: &mut Backend,
|
||||||
primitives: &[Primitive],
|
primitives: &[Primitive],
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ use crate::graphics::compositor;
|
||||||
use crate::graphics::{Error, Viewport};
|
use crate::graphics::{Error, Viewport};
|
||||||
use crate::{Backend, Primitive, Renderer, Settings};
|
use crate::{Backend, Primitive, Renderer, Settings};
|
||||||
|
|
||||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
/// A window graphics backend for iced powered by `wgpu`.
|
/// A window graphics backend for iced powered by `wgpu`.
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct Compositor<Theme> {
|
pub struct Compositor<W, Theme> {
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
instance: wgpu::Instance,
|
instance: wgpu::Instance,
|
||||||
adapter: wgpu::Adapter,
|
adapter: wgpu::Adapter,
|
||||||
|
|
@ -20,15 +20,18 @@ pub struct Compositor<Theme> {
|
||||||
queue: wgpu::Queue,
|
queue: wgpu::Queue,
|
||||||
format: wgpu::TextureFormat,
|
format: wgpu::TextureFormat,
|
||||||
theme: PhantomData<Theme>,
|
theme: PhantomData<Theme>,
|
||||||
|
w: PhantomData<W>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Theme> Compositor<Theme> {
|
impl<W: HasWindowHandle + HasDisplayHandle + wgpu::WasmNotSendSync, Theme>
|
||||||
|
Compositor<W, Theme>
|
||||||
|
{
|
||||||
/// Requests a new [`Compositor`] with the given [`Settings`].
|
/// Requests a new [`Compositor`] with the given [`Settings`].
|
||||||
///
|
///
|
||||||
/// Returns `None` if no compatible graphics adapter could be found.
|
/// Returns `None` if no compatible graphics adapter could be found.
|
||||||
pub async fn request<W: HasRawWindowHandle + HasRawDisplayHandle>(
|
pub async fn request(
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
compatible_window: Option<&W>,
|
compatible_window: Option<W>,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||||
backends: settings.internal_backend,
|
backends: settings.internal_backend,
|
||||||
|
|
@ -41,6 +44,7 @@ impl<Theme> Compositor<Theme> {
|
||||||
if log::max_level() >= log::LevelFilter::Info {
|
if log::max_level() >= log::LevelFilter::Info {
|
||||||
let available_adapters: Vec<_> = instance
|
let available_adapters: Vec<_> = instance
|
||||||
.enumerate_adapters(settings.internal_backend)
|
.enumerate_adapters(settings.internal_backend)
|
||||||
|
.iter()
|
||||||
.map(|adapter| adapter.get_info())
|
.map(|adapter| adapter.get_info())
|
||||||
.collect();
|
.collect();
|
||||||
log::info!("Available adapters: {available_adapters:#?}");
|
log::info!("Available adapters: {available_adapters:#?}");
|
||||||
|
|
@ -48,7 +52,7 @@ impl<Theme> Compositor<Theme> {
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
let compatible_surface = compatible_window
|
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
|
let adapter = instance
|
||||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||||
|
|
@ -100,14 +104,14 @@ impl<Theme> Compositor<Theme> {
|
||||||
|
|
||||||
let (device, queue) =
|
let (device, queue) =
|
||||||
loop {
|
loop {
|
||||||
let limits = limits.next()?;
|
let required_limits = limits.next()?;
|
||||||
let device = adapter.request_device(
|
let device = adapter.request_device(
|
||||||
&wgpu::DeviceDescriptor {
|
&wgpu::DeviceDescriptor {
|
||||||
label: Some(
|
label: Some(
|
||||||
"iced_wgpu::window::compositor device descriptor",
|
"iced_wgpu::window::compositor device descriptor",
|
||||||
),
|
),
|
||||||
features: wgpu::Features::empty(),
|
required_features: wgpu::Features::empty(),
|
||||||
limits,
|
required_limits,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
).await.ok();
|
).await.ok();
|
||||||
|
|
@ -125,6 +129,7 @@ impl<Theme> Compositor<Theme> {
|
||||||
queue,
|
queue,
|
||||||
format,
|
format,
|
||||||
theme: PhantomData,
|
theme: PhantomData,
|
||||||
|
w: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,10 +141,13 @@ impl<Theme> Compositor<Theme> {
|
||||||
|
|
||||||
/// Creates a [`Compositor`] and its [`Backend`] for the given [`Settings`] and
|
/// Creates a [`Compositor`] and its [`Backend`] for the given [`Settings`] and
|
||||||
/// window.
|
/// window.
|
||||||
pub fn new<Theme, W: HasRawWindowHandle + HasRawDisplayHandle>(
|
pub fn new<
|
||||||
|
Theme,
|
||||||
|
W: HasWindowHandle + HasDisplayHandle + wgpu::WasmNotSendSync,
|
||||||
|
>(
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
compatible_window: Option<&W>,
|
compatible_window: Option<W>,
|
||||||
) -> Result<Compositor<Theme>, Error> {
|
) -> Result<Compositor<W, Theme>, Error> {
|
||||||
let compositor = futures::executor::block_on(Compositor::request(
|
let compositor = futures::executor::block_on(Compositor::request(
|
||||||
settings,
|
settings,
|
||||||
compatible_window,
|
compatible_window,
|
||||||
|
|
@ -150,10 +158,10 @@ pub fn new<Theme, W: HasRawWindowHandle + HasRawDisplayHandle>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Presents the given primitives with the given [`Compositor`] and [`Backend`].
|
/// Presents the given primitives with the given [`Compositor`] and [`Backend`].
|
||||||
pub fn present<Theme, T: AsRef<str>>(
|
pub fn present<W, Theme, T: AsRef<str>>(
|
||||||
compositor: &mut Compositor<Theme>,
|
compositor: &mut Compositor<W, Theme>,
|
||||||
backend: &mut Backend,
|
backend: &mut Backend,
|
||||||
surface: &mut wgpu::Surface,
|
surface: &mut wgpu::Surface<'static>,
|
||||||
primitives: &[Primitive],
|
primitives: &[Primitive],
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
background_color: Color,
|
background_color: Color,
|
||||||
|
|
@ -204,14 +212,19 @@ pub fn present<Theme, T: AsRef<str>>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Theme> graphics::Compositor for Compositor<Theme> {
|
impl<
|
||||||
|
W: HasDisplayHandle + HasWindowHandle + wgpu::WasmNotSendSync + 'static,
|
||||||
|
Theme,
|
||||||
|
> graphics::Compositor<W> for Compositor<W, Theme>
|
||||||
|
{
|
||||||
type Settings = Settings;
|
type Settings = Settings;
|
||||||
type Renderer = Renderer<Theme>;
|
type Renderer = Renderer<Theme>;
|
||||||
type Surface = wgpu::Surface;
|
// XXX generic instead of 'static
|
||||||
|
type Surface = wgpu::Surface<'static>;
|
||||||
|
|
||||||
fn new<W: HasRawWindowHandle + HasRawDisplayHandle>(
|
fn new(
|
||||||
settings: Self::Settings,
|
settings: Self::Settings,
|
||||||
compatible_window: Option<&W>,
|
compatible_window: Option<W>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
new(settings, compatible_window)
|
new(settings, compatible_window)
|
||||||
}
|
}
|
||||||
|
|
@ -224,14 +237,15 @@ impl<Theme> graphics::Compositor for Compositor<Theme> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_surface<W: HasRawWindowHandle + HasRawDisplayHandle>(
|
fn create_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
window: &W,
|
window: W,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> wgpu::Surface {
|
) -> wgpu::Surface<'static> {
|
||||||
#[allow(unsafe_code)]
|
let mut surface = self
|
||||||
let mut surface = unsafe { self.instance.create_surface(window) }
|
.instance
|
||||||
|
.create_surface(window)
|
||||||
.expect("Create surface");
|
.expect("Create surface");
|
||||||
|
|
||||||
self.configure_surface(&mut surface, width, height);
|
self.configure_surface(&mut surface, width, height);
|
||||||
|
|
@ -241,7 +255,7 @@ impl<Theme> graphics::Compositor for Compositor<Theme> {
|
||||||
|
|
||||||
fn configure_surface(
|
fn configure_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
surface: &mut Self::Surface,
|
surface: &mut wgpu::Surface<'static>,
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
) {
|
) {
|
||||||
|
|
@ -255,6 +269,7 @@ impl<Theme> graphics::Compositor for Compositor<Theme> {
|
||||||
height,
|
height,
|
||||||
alpha_mode: wgpu::CompositeAlphaMode::Auto,
|
alpha_mode: wgpu::CompositeAlphaMode::Auto,
|
||||||
view_formats: vec![],
|
view_formats: vec![],
|
||||||
|
desired_maximum_frame_latency: 2,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -271,7 +286,7 @@ impl<Theme> graphics::Compositor for Compositor<Theme> {
|
||||||
fn present<T: AsRef<str>>(
|
fn present<T: AsRef<str>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
renderer: &mut Self::Renderer,
|
renderer: &mut Self::Renderer,
|
||||||
surface: &mut Self::Surface,
|
surface: &mut wgpu::Surface<'static>,
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
background_color: Color,
|
background_color: Color,
|
||||||
overlay: &[T],
|
overlay: &[T],
|
||||||
|
|
@ -292,7 +307,7 @@ impl<Theme> graphics::Compositor for Compositor<Theme> {
|
||||||
fn screenshot<T: AsRef<str>>(
|
fn screenshot<T: AsRef<str>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
renderer: &mut Self::Renderer,
|
renderer: &mut Self::Renderer,
|
||||||
_surface: &mut Self::Surface,
|
_surface: &mut wgpu::Surface<'static>,
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
background_color: Color,
|
background_color: Color,
|
||||||
overlay: &[T],
|
overlay: &[T],
|
||||||
|
|
@ -313,8 +328,8 @@ impl<Theme> graphics::Compositor for Compositor<Theme> {
|
||||||
/// Renders the current surface to an offscreen buffer.
|
/// Renders the current surface to an offscreen buffer.
|
||||||
///
|
///
|
||||||
/// Returns RGBA bytes of the texture data.
|
/// Returns RGBA bytes of the texture data.
|
||||||
pub fn screenshot<Theme, T: AsRef<str>>(
|
pub fn screenshot<W, Theme, T: AsRef<str>>(
|
||||||
compositor: &Compositor<Theme>,
|
compositor: &Compositor<W, Theme>,
|
||||||
backend: &mut Backend,
|
backend: &mut Backend,
|
||||||
primitives: &[Primitive],
|
primitives: &[Primitive],
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ use crate::{Clipboard, Error, Proxy, Settings};
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
|
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// An interactive, native cross-platform application.
|
/// An interactive, native cross-platform application.
|
||||||
///
|
///
|
||||||
|
|
@ -105,7 +106,7 @@ pub fn run<A, E, C>(
|
||||||
where
|
where
|
||||||
A: Application + 'static,
|
A: Application + 'static,
|
||||||
E: Executor + 'static,
|
E: Executor + 'static,
|
||||||
C: Compositor<Renderer = A::Renderer> + 'static,
|
C: Compositor<Arc<winit::window::Window>, Renderer = A::Renderer> + 'static,
|
||||||
<A::Renderer as core::Renderer>::Theme: StyleSheet,
|
<A::Renderer as core::Renderer>::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
use futures::task;
|
use futures::task;
|
||||||
|
|
@ -149,9 +150,12 @@ where
|
||||||
|
|
||||||
log::debug!("Window builder: {builder:#?}");
|
log::debug!("Window builder: {builder:#?}");
|
||||||
|
|
||||||
let window = builder
|
// XXX Arc?
|
||||||
.build(&event_loop)
|
let window = Arc::new(
|
||||||
.map_err(Error::WindowCreationFailed)?;
|
builder
|
||||||
|
.build(&event_loop)
|
||||||
|
.map_err(Error::WindowCreationFailed)?,
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[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();
|
let mut renderer = compositor.create_renderer();
|
||||||
|
|
||||||
for font in settings.fonts {
|
for font in settings.fonts {
|
||||||
|
|
@ -248,13 +252,13 @@ async fn run_instance<A, E, C>(
|
||||||
>,
|
>,
|
||||||
mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>,
|
mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>,
|
||||||
init_command: Command<A::Message>,
|
init_command: Command<A::Message>,
|
||||||
window: winit::window::Window,
|
window: Arc<winit::window::Window>,
|
||||||
should_be_visible: bool,
|
should_be_visible: bool,
|
||||||
exit_on_close_request: bool,
|
exit_on_close_request: bool,
|
||||||
) where
|
) where
|
||||||
A: Application + 'static,
|
A: Application + 'static,
|
||||||
E: Executor + 'static,
|
E: Executor + 'static,
|
||||||
C: Compositor<Renderer = A::Renderer> + 'static,
|
C: Compositor<Arc<winit::window::Window>, Renderer = A::Renderer> + 'static,
|
||||||
<A::Renderer as core::Renderer>::Theme: StyleSheet,
|
<A::Renderer as core::Renderer>::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
|
|
@ -268,7 +272,7 @@ async fn run_instance<A, E, C>(
|
||||||
let mut clipboard = Clipboard::connect(&window);
|
let mut clipboard = Clipboard::connect(&window);
|
||||||
let mut cache = user_interface::Cache::default();
|
let mut cache = user_interface::Cache::default();
|
||||||
let mut surface = compositor.create_surface(
|
let mut surface = compositor.create_surface(
|
||||||
&window,
|
window.clone(),
|
||||||
physical_size.width,
|
physical_size.width,
|
||||||
physical_size.height,
|
physical_size.height,
|
||||||
);
|
);
|
||||||
|
|
@ -608,7 +612,7 @@ pub fn update<A: Application, C, E: Executor>(
|
||||||
messages: &mut Vec<A::Message>,
|
messages: &mut Vec<A::Message>,
|
||||||
window: &winit::window::Window,
|
window: &winit::window::Window,
|
||||||
) where
|
) where
|
||||||
C: Compositor<Renderer = A::Renderer> + 'static,
|
C: Compositor<Arc<winit::window::Window>, Renderer = A::Renderer> + 'static,
|
||||||
<A::Renderer as core::Renderer>::Theme: StyleSheet,
|
<A::Renderer as core::Renderer>::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
for message in messages.drain(..) {
|
for message in messages.drain(..) {
|
||||||
|
|
@ -659,7 +663,7 @@ pub fn run_command<A, C, E>(
|
||||||
) where
|
) where
|
||||||
A: Application,
|
A: Application,
|
||||||
E: Executor,
|
E: Executor,
|
||||||
C: Compositor<Renderer = A::Renderer> + 'static,
|
C: Compositor<Arc<winit::window::Window>, Renderer = A::Renderer> + 'static,
|
||||||
<A::Renderer as core::Renderer>::Theme: StyleSheet,
|
<A::Renderer as core::Renderer>::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
use crate::runtime::command;
|
use crate::runtime::command;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ enum State {
|
||||||
impl Clipboard {
|
impl Clipboard {
|
||||||
/// Creates a new [`Clipboard`] for the given window.
|
/// Creates a new [`Clipboard`] for the given window.
|
||||||
pub fn connect(window: &winit::window::Window) -> Clipboard {
|
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()
|
.ok()
|
||||||
.map(State::Connected)
|
.map(State::Connected)
|
||||||
.unwrap_or(State::Unavailable);
|
.unwrap_or(State::Unavailable);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue