Skip to content

Commit

Permalink
Safe surface lifetime via Arc<Window>
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy committed Jan 23, 2024
1 parent ff5ef2a commit 34eaf55
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 26 deletions.
23 changes: 13 additions & 10 deletions crates/kas-core/src/app/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::draw::DrawSharedImpl;
use crate::draw::{color::Rgba, DrawIface, WindowCommon};
use crate::geom::Size;
use crate::theme::Theme;
use raw_window_handle as raw;
use raw_window_handle as rwh;
use std::time::Instant;
use thiserror::Error;

Expand All @@ -22,7 +22,7 @@ use thiserror::Error;
pub enum Error {
/// Window-handle error
#[error(transparent)]
Handle(#[from] raw::HandleError),
Handle(#[from] rwh::HandleError),

/// Failure from the graphics sub-system
#[error("error from graphics sub-system")]
Expand Down Expand Up @@ -189,6 +189,17 @@ pub trait AppGraphicsBuilder {

/// Construct shared state
fn build(self) -> Result<Self::Shared>;

/// Construct a window surface
///
/// It is required to call [`WindowSurface::do_resize`] after this.
fn new_surface<'window, W>(
shared: &mut Self::Shared,
window: W,
) -> Result<Self::Surface<'window>>
where
W: rwh::HasWindowHandle + rwh::HasDisplayHandle + Send + Sync + 'window,
Self: Sized;
}

/// Window graphical surface requirements
Expand All @@ -198,14 +209,6 @@ pub trait WindowSurface {
/// Shared draw state
type Shared: kas::draw::DrawSharedImpl;

/// Construct an instance from a window handle
///
/// It is required to call [`WindowSurface::do_resize`] after this.
fn new<W>(shared: &mut Self::Shared, window: W) -> Result<Self>
where
W: raw::HasWindowHandle + raw::HasDisplayHandle + Send + Sync,
Self: Sized;

/// Get current surface size
fn size(&self) -> Size;

Expand Down
4 changes: 2 additions & 2 deletions crates/kas-core/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ enum ProxyAction {
#[cfg(test)]
mod test {
use super::*;
use raw_window_handle as raw;
use raw_window_handle as rwh;
use std::time::Instant;

struct Draw;
Expand Down Expand Up @@ -250,7 +250,7 @@ mod test {

fn new<W>(_: &mut Self::Shared, _: W) -> Result<Self>
where
W: raw::HasRawWindowHandle + raw::HasRawDisplayHandle,
W: rwh::HasRawWindowHandle + rwh::HasRawDisplayHandle,
Self: Sized,
{
todo!()
Expand Down
7 changes: 5 additions & 2 deletions crates/kas-core/src/app/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use kas::theme::{DrawCx, SizeCx, ThemeSize};
use kas::theme::{Theme, Window as _};
use kas::{autoimpl, messages::MessageStack, Action, Id, Layout, LayoutExt, Widget, WindowId};
use std::mem::take;
use std::sync::Arc;
use std::time::{Duration, Instant};
use winit::event::WindowEvent;
use winit::event_loop::EventLoopWindowTarget;
Expand All @@ -25,7 +26,7 @@ use winit::window::WindowBuilder;
/// Window fields requiring a frame or surface
#[crate::autoimpl(Deref, DerefMut using self.window)]
struct WindowData<G: AppGraphicsBuilder, T: Theme<G::Shared>> {
window: winit::window::Window,
window: Arc<winit::window::Window>,
#[cfg(all(wayland_platform, feature = "clipboard"))]
wayland_clipboard: Option<smithay_clipboard::Clipboard>,
surface: G::Surface<'static>,
Expand Down Expand Up @@ -170,7 +171,9 @@ impl<A: AppData, G: AppGraphicsBuilder, T: Theme<G::Shared>> Window<A, G, T> {
_ => None,
};

let mut surface = G::Surface::new(&mut state.shared.draw.draw, &window)?;
// NOTE: usage of Arc is inelegant, but avoids lots of unsafe code
let window = Arc::new(window);
let mut surface = G::new_surface(&mut state.shared.draw.draw, window.clone())?;
if apply_size {
surface.do_resize(&mut state.shared.draw.draw, size);
}
Expand Down
12 changes: 12 additions & 0 deletions crates/kas-wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ mod surface;
use crate::draw::{CustomPipeBuilder, DrawPipe};
use kas::app::{AppBuilder, AppGraphicsBuilder, Result};
use kas::theme::{FlatTheme, Theme};
use wgpu::rwh;

pub use draw_shaded::{DrawShaded, DrawShadedImpl};
pub use options::Options;
Expand Down Expand Up @@ -56,6 +57,17 @@ impl<CB: CustomPipeBuilder> AppGraphicsBuilder for WgpuBuilder<CB> {
}
DrawPipe::new(self.custom, &options)
}

fn new_surface<'window, W>(
shared: &mut Self::Shared,
window: W,
) -> Result<Self::Surface<'window>>
where
W: rwh::HasWindowHandle + rwh::HasDisplayHandle + Send + Sync + 'window,
Self: Sized,
{
surface::Surface::new(shared, window)
}
}

impl Default for WgpuBuilder<()> {
Expand Down
24 changes: 12 additions & 12 deletions crates/kas-wgpu/src/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//! WGPU window surface
use crate::draw::{CustomPipe, DrawPipe, DrawWindow};
use kas::app::{raw_window_handle as raw, Error, WindowSurface};
use kas::app::{raw_window_handle as rwh, Error, WindowSurface};
use kas::cast::Cast;
use kas::draw::color::Rgba;
use kas::draw::{DrawIface, DrawSharedImpl, WindowCommon};
Expand All @@ -20,20 +20,16 @@ pub struct Surface<'a, C: CustomPipe> {
draw: DrawWindow<C::Window>,
}

impl<'a, C: CustomPipe> WindowSurface for Surface<'a, C> {
type Shared = DrawPipe<C>;

fn new<W>(shared: &mut Self::Shared, window: W) -> Result<Self, Error>
impl<'a, C: CustomPipe> Surface<'a, C> {
pub fn new<W>(shared: &mut <Self as WindowSurface>::Shared, window: W) -> Result<Self, Error>
where
W: raw::HasWindowHandle + raw::HasDisplayHandle + Send + Sync,
W: rwh::HasWindowHandle + rwh::HasDisplayHandle + Send + Sync + 'a,
Self: Sized,
{
let surface = unsafe {
// TODO: handle window lifetime safely
let target = wgpu::SurfaceTargetUnsafe::from_window(&window)?;
shared.instance.create_surface_unsafe(target)
}
.map_err(|e| Error::Graphics(Box::new(e)))?;
let surface = shared
.instance
.create_surface(window)
.map_err(|e| Error::Graphics(Box::new(e)))?;
let sc_desc = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: crate::draw::RENDER_TEX_FORMAT,
Expand All @@ -55,6 +51,10 @@ impl<'a, C: CustomPipe> WindowSurface for Surface<'a, C> {
draw: shared.new_window(),
})
}
}

impl<'a, C: CustomPipe> WindowSurface for Surface<'a, C> {
type Shared = DrawPipe<C>;

fn size(&self) -> Size {
Size::new(self.sc_desc.width.cast(), self.sc_desc.height.cast())
Expand Down

0 comments on commit 34eaf55

Please sign in to comment.