Added Wayland support
This commit is contained in:
parent
d4dea5a95f
commit
d8087a68a0
5 changed files with 85 additions and 2 deletions
|
|
@ -15,3 +15,10 @@ pub enum SoftBufferError<W: HasRawWindowHandle> {
|
|||
#[error("Platform error")]
|
||||
PlatformError(Option<String>, Option<Box<dyn Error>>)
|
||||
}
|
||||
|
||||
pub(crate) fn unwrap<T, E: std::error::Error + 'static, W: HasRawWindowHandle>(res: Result<T, E>, str: &str) -> Result<T, SoftBufferError<W>>{
|
||||
match res{
|
||||
Ok(t) => Ok(t),
|
||||
Err(e) => Err(SoftBufferError::PlatformError(Some(str.into()), Some(Box::new(e))))
|
||||
}
|
||||
}
|
||||
|
|
@ -10,8 +10,11 @@ mod win32;
|
|||
mod cg;
|
||||
#[cfg(target_os = "linux")]
|
||||
mod x11;
|
||||
#[cfg(target_os = "linux")]
|
||||
mod wayland;
|
||||
|
||||
mod error;
|
||||
|
||||
pub use error::SoftBufferError;
|
||||
|
||||
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
|
||||
|
|
@ -33,9 +36,11 @@ impl<W: HasRawWindowHandle> GraphicsContext<W> {
|
|||
/// - Ensure that the passed object is valid to draw a 2D buffer to
|
||||
pub unsafe fn new(window: W) -> Result<Self, SoftBufferError<W>> {
|
||||
let raw_handle = window.raw_window_handle();
|
||||
let imple = match raw_handle {
|
||||
let imple: Box<dyn GraphicsContextImpl> = match raw_handle {
|
||||
#[cfg(target_os = "linux")]
|
||||
RawWindowHandle::Xlib(xlib_handle) => Box::new(x11::X11Impl::new(xlib_handle)?),
|
||||
#[cfg(target_os = "linux")]
|
||||
RawWindowHandle::Wayland(wayland_handle) => Box::new(wayland::WaylandImpl::new(wayland_handle)?),
|
||||
#[cfg(target_os = "windows")]
|
||||
RawWindowHandle::Win32(win32_handle) => Box::new(win32::Win32Impl::new(&win32_handle)?),
|
||||
#[cfg(target_os = "macos")]
|
||||
|
|
|
|||
69
src/wayland.rs
Normal file
69
src/wayland.rs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
use raw_window_handle::{HasRawWindowHandle, WaylandHandle};
|
||||
use tempfile::tempfile;
|
||||
use wayland_client::{Display, sys::client::wl_display, GlobalManager, protocol::{wl_shm::WlShm, wl_buffer::WlBuffer, wl_surface::WlSurface}, Main, Proxy, EventQueue};
|
||||
use crate::{GraphicsContextImpl, SoftBufferError, error::unwrap};
|
||||
use std::{fs::File, os::unix::prelude::{AsRawFd, FileExt}, io::Write};
|
||||
|
||||
pub struct WaylandImpl {
|
||||
_event_queue: EventQueue,
|
||||
surface: WlSurface,
|
||||
shm: Main<WlShm>,
|
||||
tempfile: File,
|
||||
buffer: Option<WaylandBuffer>
|
||||
}
|
||||
|
||||
struct WaylandBuffer{
|
||||
width: i32,
|
||||
height: i32,
|
||||
buffer: Main<WlBuffer>
|
||||
}
|
||||
|
||||
impl WaylandImpl {
|
||||
|
||||
pub unsafe fn new<W: HasRawWindowHandle>(handle: WaylandHandle) -> Result<Self, SoftBufferError<W>> {
|
||||
let display = Display::from_external_display(handle.display as *mut wl_display);
|
||||
let mut event_queue = display.create_event_queue();
|
||||
let attached_display = (*display).clone().attach(event_queue.token());
|
||||
let globals = GlobalManager::new(&attached_display);
|
||||
unwrap(event_queue.sync_roundtrip(&mut (), |_, _, _| unreachable!()), "Failed to make round trip to server")?;
|
||||
let shm = unwrap(globals.instantiate_exact::<WlShm>(1), "Failed to instantiate Wayland Shm")?;
|
||||
let tempfile = unwrap(tempfile(), "Failed to create temporary file to store buffer.")?;
|
||||
let surface = Proxy::from_c_ptr(handle.surface as _).into();
|
||||
Ok(Self{
|
||||
_event_queue: event_queue,
|
||||
surface, shm, tempfile,
|
||||
buffer: None
|
||||
})
|
||||
}
|
||||
|
||||
fn ensure_buffer_size(&mut self, width: i32, height: i32){
|
||||
if !self.check_buffer_size_equals(width, height){
|
||||
let pool = self.shm.create_pool(self.tempfile.as_raw_fd(), width*height*4);
|
||||
let buffer = pool.create_buffer(0, width, height, width*4, wayland_client::protocol::wl_shm::Format::Xrgb8888);
|
||||
self.buffer = Some(WaylandBuffer{
|
||||
width,
|
||||
height,
|
||||
buffer
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn check_buffer_size_equals(&self, width: i32, height: i32) -> bool{
|
||||
match &self.buffer{
|
||||
Some(buffer) => buffer.width == width && buffer.height == height,
|
||||
None => false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl GraphicsContextImpl for WaylandImpl {
|
||||
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
||||
self.ensure_buffer_size(width as i32, height as i32);
|
||||
let wayland_buffer = self.buffer.as_mut().unwrap();
|
||||
self.tempfile.write_at(std::slice::from_raw_parts(buffer.as_ptr() as *const u8, buffer.len()*4), 0).expect("Failed to write buffer to temporary file.");
|
||||
self.tempfile.flush().expect("Failed to flush buffer to temporary file.");
|
||||
self.surface.attach(Some(&wayland_buffer.buffer), 0, 0);
|
||||
self.surface.commit();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue