Skip to content

Commit

Permalink
Move new() methods into traits
Browse files Browse the repository at this point in the history
Now `lib.rs` doesn't need conditional code and macros for dispatching
`new`. It can be handled by `make_dispatch!`.
  • Loading branch information
ids1024 committed Feb 13, 2024
1 parent c0ff669 commit d7b32fa
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 235 deletions.
37 changes: 35 additions & 2 deletions src/backend_dispatch.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Implements `buffer_interface::*` traits for enums dispatching to backends
use crate::{backend_interface::*, backends, Rect, SoftBufferError};
use crate::{backend_interface::*, backends, InitError, Rect, SoftBufferError};

use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use std::num::NonZeroU32;
Expand Down Expand Up @@ -35,6 +35,26 @@ macro_rules! make_dispatch {
}
}

impl<D: HasDisplayHandle> ContextInterface<D> for ContextDispatch<D> {
fn new(mut display: D) -> Result<Self, InitError<D>>
where
D: Sized,
{
$(
$(#[$attr])*
match <$context_inner as ContextInterface<D>>::new(display) {
Ok(x) => {
return Ok(Self::$name(x));
}
Err(InitError::Unsupported(d)) => display = d,
Err(InitError::Failure(f)) => return Err(InitError::Failure(f)),
}
)*

Err(InitError::Unsupported(display))
}
}

#[allow(clippy::large_enum_variant)] // it's boxed anyways
pub(crate) enum SurfaceDispatch<$dgen, $wgen> {
$(
Expand All @@ -43,9 +63,22 @@ macro_rules! make_dispatch {
)*
}

impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<W> for SurfaceDispatch<D, W> {
impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for SurfaceDispatch<D, W> {
type Context = ContextDispatch<D>;
type Buffer<'a> = BufferDispatch<'a, D, W> where Self: 'a;

fn new(window: W, display: &Self::Context) -> Result<Self, InitError<W>>
where
W: Sized,
Self: Sized {
match display {
$(
$(#[$attr])*
ContextDispatch::$name(inner) => Ok(Self::$name(<$surface_inner>::new(window, inner)?)),
)*
}
}

fn window(&self) -> &W {
match self {
$(
Expand Down
18 changes: 15 additions & 3 deletions src/backend_interface.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
//! Interface implemented by backends
use crate::{Rect, SoftBufferError};
use crate::{InitError, Rect, SoftBufferError};

use raw_window_handle::HasWindowHandle;
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use std::num::NonZeroU32;

pub(crate) trait SurfaceInterface<W: HasWindowHandle + ?Sized> {
pub(crate) trait ContextInterface<D: HasDisplayHandle + ?Sized> {
fn new(display: D) -> Result<Self, InitError<D>>
where
D: Sized,
Self: Sized;
}

pub(crate) trait SurfaceInterface<D: HasDisplayHandle + ?Sized, W: HasWindowHandle + ?Sized> {
type Context: ContextInterface<D>;
type Buffer<'a>: BufferInterface
where
Self: 'a;

fn new(window: W, context: &Self::Context) -> Result<Self, InitError<W>>
where
W: Sized,
Self: Sized;
/// Get the inner window handle.
fn window(&self) -> &W;
/// Resize the internal buffer to the given width and height.
Expand Down
11 changes: 5 additions & 6 deletions src/backends/cg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ pub struct CGImpl<D, W> {
_display: PhantomData<D>,
}

impl<D: HasDisplayHandle, W: HasWindowHandle> CGImpl<D, W> {
pub(crate) fn new(window_src: W) -> Result<Self, InitError<W>> {
impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for CGImpl<D, W> {
type Context = D;
type Buffer<'a> = BufferImpl<'a, D, W> where Self: 'a;

fn new(window_src: W, _display: &D) -> Result<Self, InitError<W>> {
let raw = window_src.window_handle()?.as_raw();
let handle = match raw {
RawWindowHandle::AppKit(handle) => handle,
Expand Down Expand Up @@ -66,10 +69,6 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> CGImpl<D, W> {
window_handle: window_src,
})
}
}

impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<W> for CGImpl<D, W> {
type Buffer<'a> = BufferImpl<'a, D, W> where Self: 'a;

#[inline]
fn window(&self) -> &W {
Expand Down
24 changes: 13 additions & 11 deletions src/backends/kms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ impl<D: ?Sized> AsFd for KmsDisplayImpl<D> {
impl<D: ?Sized> Device for KmsDisplayImpl<D> {}
impl<D: ?Sized> CtrlDevice for KmsDisplayImpl<D> {}

impl<D: HasDisplayHandle> KmsDisplayImpl<D> {
pub(crate) fn new(display: D) -> Result<Self, InitError<D>> {
impl<D: HasDisplayHandle + ?Sized> ContextInterface<D> for Rc<KmsDisplayImpl<D>> {
fn new(display: D) -> Result<Self, InitError<D>>
where
D: Sized,
{
let fd = match display.display_handle()?.as_raw() {
RawDisplayHandle::Drm(drm) => drm.fd,
_ => return Err(InitError::Unsupported(display)),
Expand All @@ -51,10 +54,10 @@ impl<D: HasDisplayHandle> KmsDisplayImpl<D> {
// SAFETY: Invariants guaranteed by the user.
let fd = unsafe { BorrowedFd::borrow_raw(fd) };

Ok(KmsDisplayImpl {
Ok(Rc::new(KmsDisplayImpl {
fd,
_display: display,
})
}))
}
}

Expand Down Expand Up @@ -135,9 +138,12 @@ struct SharedBuffer {
age: u8,
}

impl<D: ?Sized, W: HasWindowHandle> KmsImpl<D, W> {
impl<D: HasDisplayHandle + ?Sized, W: HasWindowHandle> SurfaceInterface<D, W> for KmsImpl<D, W> {
type Context = Rc<KmsDisplayImpl<D>>;
type Buffer<'a> = BufferImpl<'a, D, W> where Self: 'a;

/// Create a new KMS backend.
pub(crate) fn new(window: W, display: Rc<KmsDisplayImpl<D>>) -> Result<Self, InitError<W>> {
fn new(window: W, display: &Rc<KmsDisplayImpl<D>>) -> Result<Self, InitError<W>> {
// Make sure that the window handle is valid.
let plane_handle = match window.window_handle()?.as_raw() {
RawWindowHandle::Drm(drm) => match NonZeroU32::new(drm.plane) {
Expand Down Expand Up @@ -199,15 +205,11 @@ impl<D: ?Sized, W: HasWindowHandle> KmsImpl<D, W> {
Ok(Self {
crtc,
connectors,
display,
display: display.clone(),
buffer: None,
window_handle: window,
})
}
}

impl<D: ?Sized, W: HasWindowHandle> SurfaceInterface<W> for KmsImpl<D, W> {
type Buffer<'a> = BufferImpl<'a, D, W> where Self: 'a;

#[inline]
fn window(&self) -> &W {
Expand Down
9 changes: 9 additions & 0 deletions src/backends/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use crate::{ContextInterface, InitError};
use raw_window_handle::HasDisplayHandle;

#[cfg(target_os = "macos")]
pub(crate) mod cg;
#[cfg(kms_platform)]
Expand All @@ -12,3 +15,9 @@ pub(crate) mod web;
pub(crate) mod win32;
#[cfg(x11_platform)]
pub(crate) mod x11;

impl<D: HasDisplayHandle> ContextInterface<D> for D {
fn new(display: D) -> Result<Self, InitError<D>> {
Ok(display)
}
}
37 changes: 19 additions & 18 deletions src/backends/orbital.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,23 +65,6 @@ pub struct OrbitalImpl<D, W> {
}

impl<D: HasDisplayHandle, W: HasWindowHandle> OrbitalImpl<D, W> {
pub(crate) fn new(window: W) -> Result<Self, InitError<W>> {
let raw = window.window_handle()?.as_raw();
let handle = match raw {
RawWindowHandle::Orbital(handle) => handle,
_ => return Err(InitError::Unsupported(window)),
};

Ok(Self {
handle,
width: 0,
height: 0,
presented: false,
window_handle: window,
_display: PhantomData,
})
}

fn window_fd(&self) -> usize {
self.handle.window.as_ptr() as usize
}
Expand Down Expand Up @@ -139,9 +122,27 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> OrbitalImpl<D, W> {
}
}

impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<W> for OrbitalImpl<D, W> {
impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for OrbitalImpl<D, W> {
type Context = D;
type Buffer<'a> = BufferImpl<'a, D, W> where Self: 'a;

fn new(window: W, _display: &D) -> Result<Self, InitError<W>> {
let raw = window.window_handle()?.as_raw();
let handle = match raw {
RawWindowHandle::Orbital(handle) => handle,
_ => return Err(InitError::Unsupported(window)),
};

Ok(Self {
handle,
width: 0,
height: 0,
presented: false,
window_handle: window,
_display: PhantomData,
})
}

#[inline]
fn window(&self) -> &W {
&self.window_handle
Expand Down
73 changes: 39 additions & 34 deletions src/backends/wayland/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ pub struct WaylandDisplayImpl<D: ?Sized> {
}

impl<D: HasDisplayHandle + ?Sized> WaylandDisplayImpl<D> {
pub(crate) fn new(display: D) -> Result<Self, InitError<D>>
fn conn(&self) -> &Connection {
self.conn.as_ref().unwrap()
}
}

impl<D: HasDisplayHandle + ?Sized> ContextInterface<D> for Rc<WaylandDisplayImpl<D>> {
fn new(display: D) -> Result<Self, InitError<D>>
where
D: Sized,
{
Expand All @@ -53,17 +59,13 @@ impl<D: HasDisplayHandle + ?Sized> WaylandDisplayImpl<D> {
let shm: wl_shm::WlShm = globals
.bind(&qh, 1..=1, ())
.swbuf_err("Failed to instantiate Wayland Shm")?;
Ok(Self {
Ok(Rc::new(WaylandDisplayImpl {
conn: Some(conn),
event_queue: RefCell::new(event_queue),
qh,
shm,
_display: display,
})
}

fn conn(&self) -> &Connection {
self.conn.as_ref().unwrap()
}))
}
}

Expand All @@ -88,32 +90,6 @@ pub struct WaylandImpl<D: ?Sized, W: ?Sized> {
}

impl<D: HasDisplayHandle + ?Sized, W: HasWindowHandle> WaylandImpl<D, W> {
pub(crate) fn new(window: W, display: Rc<WaylandDisplayImpl<D>>) -> Result<Self, InitError<W>> {
// Get the raw Wayland window.
let raw = window.window_handle()?.as_raw();
let wayland_handle = match raw {
RawWindowHandle::Wayland(w) => w.surface,
_ => return Err(InitError::Unsupported(window)),
};

let surface_id = unsafe {
ObjectId::from_ptr(
wl_surface::WlSurface::interface(),
wayland_handle.as_ptr().cast(),
)
}
.swbuf_err("Failed to create proxy for surface ID.")?;
let surface = wl_surface::WlSurface::from_id(display.conn(), surface_id)
.swbuf_err("Failed to create proxy for surface ID.")?;
Ok(Self {
display,
surface: Some(surface),
buffers: Default::default(),
size: None,
window_handle: window,
})
}

fn surface(&self) -> &wl_surface::WlSurface {
self.surface.as_ref().unwrap()
}
Expand Down Expand Up @@ -166,9 +142,38 @@ impl<D: HasDisplayHandle + ?Sized, W: HasWindowHandle> WaylandImpl<D, W> {
}
}

impl<D: HasDisplayHandle + ?Sized, W: HasWindowHandle> SurfaceInterface<W> for WaylandImpl<D, W> {
impl<D: HasDisplayHandle + ?Sized, W: HasWindowHandle> SurfaceInterface<D, W>
for WaylandImpl<D, W>
{
type Context = Rc<WaylandDisplayImpl<D>>;
type Buffer<'a> = BufferImpl<'a, D, W> where Self: 'a;

fn new(window: W, display: &Rc<WaylandDisplayImpl<D>>) -> Result<Self, InitError<W>> {
// Get the raw Wayland window.
let raw = window.window_handle()?.as_raw();
let wayland_handle = match raw {
RawWindowHandle::Wayland(w) => w.surface,
_ => return Err(InitError::Unsupported(window)),
};

let surface_id = unsafe {
ObjectId::from_ptr(
wl_surface::WlSurface::interface(),
wayland_handle.as_ptr().cast(),
)
}
.swbuf_err("Failed to create proxy for surface ID.")?;
let surface = wl_surface::WlSurface::from_id(display.conn(), surface_id)
.swbuf_err("Failed to create proxy for surface ID.")?;
Ok(Self {
display: display.clone(),
surface: Some(surface),
buffers: Default::default(),
size: None,
window_handle: window,
})
}

#[inline]
fn window(&self) -> &W {
&self.window_handle
Expand Down
Loading

0 comments on commit d7b32fa

Please sign in to comment.