From 1f44e3ab5ad7af2988b8aebc381e46d10de711b5 Mon Sep 17 00:00:00 2001 From: John Nunley Date: Sat, 21 Oct 2023 22:38:48 -0700 Subject: [PATCH] Update for newest changes Signed-off-by: John Nunley --- Cargo.toml | 3 -- src/cg.rs | 9 +++-- src/kms.rs | 87 +++++++++++++++++++++++++--------------------- src/lib.rs | 24 ++++++------- src/orbital.rs | 8 ++--- src/wayland/mod.rs | 16 ++++----- src/web.rs | 13 ++----- src/win32.rs | 11 ++---- src/x11.rs | 55 ++++++++++++++--------------- 9 files changed, 105 insertions(+), 121 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b0ad381..892dfd6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -120,6 +120,3 @@ targets = [ "wasm32-unknown-unknown", ] -[patch.crates-io] -raw_window_handle = { package = "raw-window-handle", git = "https://github.com/rust-windowing/raw-window-handle.git", branch = "notgull/next" } -winit = { git = "https://github.com/forkgull/winit.git", branch = "rwh-0.6" } diff --git a/src/cg.rs b/src/cg.rs index 4ebb458..97cc913 100644 --- a/src/cg.rs +++ b/src/cg.rs @@ -6,7 +6,7 @@ use core_graphics::base::{ use core_graphics::color_space::CGColorSpace; use core_graphics::data_provider::CGDataProvider; use core_graphics::image::CGImage; -use raw_window_handle::{HasDisplayHandle, HasRawWindowHandle, HasWindowHandle, RawWindowHandle}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawWindowHandle}; use cocoa::appkit::{NSView, NSViewHeightSizable, NSViewWidthSizable, NSWindow}; use cocoa::base::{id, nil}; @@ -36,14 +36,13 @@ pub struct CGImpl { impl CGImpl { pub(crate) fn new(window_src: W) -> Result> { - let raw = window_src.window_handle()?.raw_window_handle()?; + let raw = window_src.window_handle()?.as_raw(); let handle = match raw { RawWindowHandle::AppKit(handle) => handle, _ => return Err(InitError::Unsupported(window_src)), }; - let window = handle.ns_window as id; - let window: id = unsafe { msg_send![window, retain] }; - let view = handle.ns_view as id; + let view = handle.ns_view.as_ptr() as id; + let window = unsafe { msg_send![view, window] }; let layer = CALayer::new(); unsafe { let subview: id = NSView::alloc(nil).initWithFrame_(NSView::frame(view)); diff --git a/src/kms.rs b/src/kms.rs index aa7ebb5..bcbdfff 100644 --- a/src/kms.rs +++ b/src/kms.rs @@ -9,54 +9,59 @@ use drm::control::{ }; use drm::Device; -use raw_window_handle::{DrmDisplayHandle, DrmWindowHandle}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle}; use std::collections::HashSet; +use std::marker::PhantomData; use std::num::NonZeroU32; use std::os::unix::io::{AsFd, BorrowedFd}; use std::rc::Rc; -use crate::error::{SoftBufferError, SwResultExt}; +use crate::error::{InitError, SoftBufferError, SwResultExt}; #[derive(Debug)] -pub(crate) struct KmsDisplayImpl { +pub(crate) struct KmsDisplayImpl { /// The underlying raw device file descriptor. - /// - /// Once rwh v0.6 support is merged, this an be made safe. Until then, - /// we use this hacky workaround, since this FD's validity is guaranteed by - /// the unsafe constructor. fd: BorrowedFd<'static>, + + /// Holds a reference to the display. + _display: D, } -impl AsFd for KmsDisplayImpl { +impl AsFd for KmsDisplayImpl { fn as_fd(&self) -> BorrowedFd<'_> { self.fd } } -impl Device for KmsDisplayImpl {} -impl CtrlDevice for KmsDisplayImpl {} +impl Device for KmsDisplayImpl {} +impl CtrlDevice for KmsDisplayImpl {} -impl KmsDisplayImpl { - /// SAFETY: The underlying fd must not outlive the display. - pub(crate) unsafe fn new(handle: DrmDisplayHandle) -> Result { - let fd = handle.fd; +impl KmsDisplayImpl { + pub(crate) fn new(display: D) -> Result> { + let fd = match display.display_handle()?.as_raw() { + RawDisplayHandle::Drm(drm) => drm.fd, + _ => return Err(InitError::Unsupported(display)), + }; if fd == -1 { - return Err(SoftBufferError::IncompleteDisplayHandle); + return Err(SoftBufferError::IncompleteDisplayHandle.into()); } // SAFETY: Invariants guaranteed by the user. let fd = unsafe { BorrowedFd::borrow_raw(fd) }; - Ok(KmsDisplayImpl { fd }) + Ok(KmsDisplayImpl { + fd, + _display: display, + }) } } /// All the necessary types for the Drm/Kms backend. #[derive(Debug)] -pub(crate) struct KmsImpl { +pub(crate) struct KmsImpl { /// The display implementation. - display: Rc, + display: Rc>, /// The connectors to use. connectors: Vec, @@ -66,6 +71,9 @@ pub(crate) struct KmsImpl { /// The dumb buffer we're using as a buffer. buffer: Option, + + /// Window handle that we are keeping around. + _window: W, } #[derive(Debug)] @@ -81,7 +89,7 @@ struct Buffers { } /// The buffer implementation. -pub(crate) struct BufferImpl<'a> { +pub(crate) struct BufferImpl<'a, D: ?Sized, W: ?Sized> { /// The mapping of the dump buffer. mapping: DumbMapping<'a>, @@ -101,13 +109,16 @@ pub(crate) struct BufferImpl<'a> { size: (NonZeroU32, NonZeroU32), /// The display implementation. - display: &'a KmsDisplayImpl, + display: &'a KmsDisplayImpl, /// Age of the front buffer. front_age: &'a mut u8, /// Age of the back buffer. back_age: &'a mut u8, + + /// Window reference. + _window: PhantomData<&'a mut W>, } /// The combined frame buffer and dumb buffer. @@ -123,22 +134,16 @@ struct SharedBuffer { age: u8, } -impl KmsImpl { +impl KmsImpl { /// Create a new KMS backend. - /// - /// # Safety - /// - /// The plane must be valid for the lifetime of the backend. - pub(crate) unsafe fn new( - window_handle: DrmWindowHandle, - display: Rc, - ) -> Result { - log::trace!("new: window_handle={:X}", window_handle.plane); - + pub(crate) fn new(window: W, display: Rc>) -> Result> { // Make sure that the window handle is valid. - let plane_handle = match NonZeroU32::new(window_handle.plane) { - Some(handle) => plane::Handle::from(handle), - None => return Err(SoftBufferError::IncompleteWindowHandle), + let plane_handle = match window.window_handle()?.as_raw() { + RawWindowHandle::Drm(drm) => match NonZeroU32::new(drm.plane) { + Some(handle) => plane::Handle::from(handle), + None => return Err(SoftBufferError::IncompleteWindowHandle.into()), + }, + _ => return Err(InitError::Unsupported(window)), }; let plane_info = display @@ -195,6 +200,7 @@ impl KmsImpl { connectors, display, buffer: None, + _window: window, }) } @@ -232,7 +238,7 @@ impl KmsImpl { } /// Get a mutable reference to the buffer. - pub(crate) fn buffer_mut(&mut self) -> Result, SoftBufferError> { + pub(crate) fn buffer_mut(&mut self) -> Result, SoftBufferError> { // Map the dumb buffer. let set = self .buffer @@ -267,11 +273,12 @@ impl KmsImpl { zeroes: &set.zeroes, front_age, back_age, + _window: PhantomData, }) } } -impl Drop for KmsImpl { +impl Drop for KmsImpl { fn drop(&mut self) { // Map the CRTC to the information that was there before. self.display @@ -286,7 +293,7 @@ impl Drop for KmsImpl { } } -impl BufferImpl<'_> { +impl BufferImpl<'_, D, W> { #[inline] pub fn pixels(&self) -> &[u32] { // drm-rs doesn't let us have the immutable reference... so just use a bunch of zeroes. @@ -310,7 +317,7 @@ impl BufferImpl<'_> { .iter() .map(|&rect| { let err = || SoftBufferError::DamageOutOfRange { rect }; - Ok(ClipRect::new( + Ok::<_, SoftBufferError>(ClipRect::new( rect.x.try_into().map_err(|_| err())?, rect.y.try_into().map_err(|_| err())?, rect.x @@ -375,8 +382,8 @@ impl BufferImpl<'_> { impl SharedBuffer { /// Create a new buffer set. - pub(crate) fn new( - display: &KmsDisplayImpl, + pub(crate) fn new( + display: &KmsDisplayImpl, width: NonZeroU32, height: NonZeroU32, ) -> Result { diff --git a/src/lib.rs b/src/lib.rs index 152d41e..798fa96 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,10 +35,7 @@ use std::rc::Rc; use error::InitError; pub use error::SoftBufferError; -use raw_window_handle::{ - HasDisplayHandle, HasRawDisplayHandle, HasRawWindowHandle, HasWindowHandle, RawDisplayHandle, - RawWindowHandle, -}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle}; #[cfg(target_arch = "wasm32")] pub use self::web::SurfaceExtWeb; @@ -184,7 +181,7 @@ make_dispatch! { #[cfg(wayland_platform)] Wayland(Rc>, wayland::WaylandImpl, wayland::BufferImpl<'a, D, W>), #[cfg(kms_platform)] - Kms(Rc, kms::KmsImpl, kms::BufferImpl<'a>), + Kms(Rc>, kms::KmsImpl, kms::BufferImpl<'a, D, W>), #[cfg(target_os = "windows")] Win32(D, win32::Win32Impl, win32::BufferImpl<'a, D, W>), #[cfg(target_os = "macos")] @@ -213,18 +210,13 @@ impl Context { } }}; } - } - /// Creates a new instance of this struct, using the provided display handles - /// - /// # Safety - /// - /// - Ensure that the provided handle is valid for the lifetime of the Context - pub unsafe fn from_raw(raw_display_handle: RawDisplayHandle) -> Result { #[cfg(x11_platform)] try_init!(X11, display => x11::X11DisplayImpl::new(display).map(Rc::new)); #[cfg(wayland_platform)] try_init!(Wayland, display => wayland::WaylandDisplayImpl::new(display).map(Rc::new)); + #[cfg(kms_platform)] + try_init!(Kms, display => kms::KmsDisplayImpl::new(display).map(Rc::new)); #[cfg(target_os = "windows")] try_init!(Win32, display => Ok(display)); #[cfg(target_os = "macos")] @@ -234,7 +226,7 @@ impl Context { #[cfg(target_os = "redox")] try_init!(Orbital, display => Ok(display)); - let raw = dpy.display_handle()?.raw_display_handle()?; + let raw = dpy.display_handle()?.as_raw(); Err(SoftBufferError::UnsupportedDisplayPlatform { human_readable_display_platform_name: display_handle_type_name(&raw), display_handle: raw, @@ -270,7 +262,7 @@ impl Surface { match ($e) { Ok(x) => x, Err(InitError::Unsupported(window)) => { - let raw = window.window_handle()?.raw_window_handle()?; + let raw = window.window_handle()?.as_raw(); return Err(SoftBufferError::UnsupportedWindowPlatform { human_readable_window_platform_name: window_handle_type_name(&raw), human_readable_display_platform_name: context @@ -293,6 +285,10 @@ impl Surface { ContextDispatch::Wayland(wayland_display_impl) => SurfaceDispatch::Wayland(leap!( wayland::WaylandImpl::new(window, wayland_display_impl.clone()) )), + #[cfg(kms_platform)] + ContextDispatch::Kms(kms_display_impl) => { + SurfaceDispatch::Kms(leap!(kms::KmsImpl::new(window, kms_display_impl.clone()))) + } #[cfg(target_os = "windows")] ContextDispatch::Win32(_) => { SurfaceDispatch::Win32(leap!(win32::Win32Impl::new(window))) diff --git a/src/orbital.rs b/src/orbital.rs index f934889..3495b89 100644 --- a/src/orbital.rs +++ b/src/orbital.rs @@ -1,7 +1,5 @@ use crate::error::InitError; -use raw_window_handle::{ - HasDisplayHandle, HasRawWindowHandle, HasWindowHandle, OrbitalWindowHandle, RawWindowHandle, -}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle, OrbitalWindowHandle, RawWindowHandle}; use std::{cmp, marker::PhantomData, num::NonZeroU32, slice, str}; use crate::{Rect, SoftBufferError}; @@ -67,7 +65,7 @@ pub struct OrbitalImpl { impl OrbitalImpl { pub(crate) fn new(window: W) -> Result> { - let raw = window.window_handle()?.raw_window_handle()?; + let raw = window.window_handle()?.as_raw(); let handle = match raw { RawWindowHandle::Orbital(handle) => handle, _ => return Err(InitError::Unsupported(window)), @@ -95,7 +93,7 @@ impl OrbitalImpl { } fn window_fd(&self) -> usize { - self.handle.window as usize + self.handle.window.as_ptr() as usize } // Read the current width and size diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index 855dc94..762202d 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -2,10 +2,7 @@ use crate::{ error::{InitError, SwResultExt}, util, Rect, SoftBufferError, }; -use raw_window_handle::{ - HasDisplayHandle, HasRawDisplayHandle, HasRawWindowHandle, HasWindowHandle, RawDisplayHandle, - RawWindowHandle, -}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle}; use std::{ cell::RefCell, num::{NonZeroI32, NonZeroU32}, @@ -41,13 +38,13 @@ impl WaylandDisplayImpl { where D: Sized, { - let raw = display.display_handle()?.raw_display_handle()?; + let raw = display.display_handle()?.as_raw(); let wayland_handle = match raw { RawDisplayHandle::Wayland(w) => w.display, _ => return Err(InitError::Unsupported(display)), }; - let backend = unsafe { Backend::from_foreign_display(wayland_handle.cast()) }; + let backend = unsafe { Backend::from_foreign_display(wayland_handle.as_ptr().cast()) }; let conn = Connection::from_backend(backend); let (globals, event_queue) = registry_queue_init(&conn).swbuf_err("Failed to make round trip to server")?; @@ -92,14 +89,17 @@ pub struct WaylandImpl { impl WaylandImpl { pub(crate) fn new(window: W, display: Rc>) -> Result> { // Get the raw Wayland window. - let raw = window.window_handle()?.raw_window_handle()?; + 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.cast()) + 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) diff --git a/src/web.rs b/src/web.rs index 6ea71d8..1caa71e 100644 --- a/src/web.rs +++ b/src/web.rs @@ -2,15 +2,8 @@ #![allow(clippy::uninlined_format_args)] -use std::convert::TryInto; -use std::marker::PhantomData; -use std::num::NonZeroU32; - use js_sys::Object; -use raw_window_handle::{ - HasDisplayHandle, HasRawDisplayHandle, HasRawWindowHandle, HasWindowHandle, RawDisplayHandle, - RawWindowHandle, -}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle}; use wasm_bindgen::{JsCast, JsValue}; use web_sys::ImageData; use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement}; @@ -32,7 +25,7 @@ pub struct WebDisplayImpl { impl WebDisplayImpl { pub(super) fn new(display: D) -> Result> { - let raw = display.display_handle()?.raw_display_handle()?; + let raw = display.display_handle()?.as_raw(); match raw { RawDisplayHandle::Web(..) => {} _ => return Err(InitError::Unsupported(display)), @@ -85,7 +78,7 @@ enum Canvas { impl WebImpl { pub(crate) fn new(display: &WebDisplayImpl, window: W) -> Result> { - let raw = window.window_handle()?.raw_window_handle()?; + let raw = window.window_handle()?.as_raw(); let handle = match raw { RawWindowHandle::Web(handle) => handle, _ => return Err(InitError::Unsupported(window)), diff --git a/src/win32.rs b/src/win32.rs index 13b1e6e..a703aad 100644 --- a/src/win32.rs +++ b/src/win32.rs @@ -3,7 +3,7 @@ //! This module converts the input buffer into a bitmap and then stretches it to the window. use crate::{Rect, SoftBufferError}; -use raw_window_handle::{HasDisplayHandle, HasRawWindowHandle, HasWindowHandle, RawWindowHandle}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawWindowHandle}; use std::io; use std::marker::PhantomData; @@ -160,20 +160,15 @@ struct BitmapInfo { impl Win32Impl { /// Create a new `Win32Impl` from a `Win32WindowHandle`. pub(crate) fn new(window: W) -> Result> { - let raw = window.window_handle()?.raw_window_handle()?; + let raw = window.window_handle()?.as_raw(); let handle = match raw { RawWindowHandle::Win32(handle) => handle, _ => return Err(crate::InitError::Unsupported(window)), }; - // It is valid for the window handle to be null here. Error out if it is. - if handle.hwnd.is_null() { - return Err(SoftBufferError::IncompleteWindowHandle.into()); - } - // Get the handle to the device context. // SAFETY: We have confirmed that the window handle is valid. - let hwnd = handle.hwnd as HWND; + let hwnd = handle.hwnd.get() as HWND; let dc = unsafe { Gdi::GetDC(hwnd) }; // GetDC returns null if there is a platform error. diff --git a/src/x11.rs b/src/x11.rs index 0a6defb..7427e89 100644 --- a/src/x11.rs +++ b/src/x11.rs @@ -7,7 +7,10 @@ use crate::error::{InitError, SwResultExt}; use crate::{Rect, SoftBufferError}; -use raw_window_handle::{XcbDisplayHandle, XcbWindowHandle, XlibDisplayHandle, XlibWindowHandle}; +use raw_window_handle::{ + HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle, XcbDisplayHandle, + XcbWindowHandle, +}; use rustix::{fd, mm, shm as posix_shm}; use std::{ @@ -50,41 +53,40 @@ impl X11DisplayImpl { D: Sized, { // Get the underlying libxcb handle. - let raw = display.display_handle()?.raw_display_handle()?; + let raw = display.display_handle()?.as_raw(); let xcb_handle = match raw { RawDisplayHandle::Xcb(xcb_handle) => xcb_handle, RawDisplayHandle::Xlib(xlib) => { // Convert to an XCB handle. - if xlib.display.is_null() { - return Err(SoftBufferError::IncompleteDisplayHandle.into()); - } + let display = match xlib.display { + Some(display) => display, + None => return Err(SoftBufferError::IncompleteDisplayHandle.into()), + }; // Get the underlying XCB connection. // SAFETY: The user has asserted that the display handle is valid. let connection = unsafe { - let display = tiny_xlib::Display::from_ptr(xlib.display); - display.as_raw_xcb_connection() + let display = tiny_xlib::Display::from_ptr(display.as_ptr()); + NonNull::new_unchecked(display.as_raw_xcb_connection()) }; // Construct the equivalent XCB display and window handles. - let mut xcb_display_handle = XcbDisplayHandle::empty(); - xcb_display_handle.connection = connection.cast(); - xcb_display_handle.screen = xlib.screen; - xcb_display_handle + XcbDisplayHandle::new(Some(connection.cast()), xlib.screen) } _ => return Err(InitError::Unsupported(display)), }; // Validate the display handle to ensure we can use it. - if xcb_handle.connection.is_null() { - return Err(SoftBufferError::IncompleteDisplayHandle.into()); - } + let connection = match xcb_handle.connection { + Some(conn) => conn, + None => return Err(SoftBufferError::IncompleteDisplayHandle.into()), + }; // Wrap the display handle in an x11rb connection. // SAFETY: We don't own the connection, so don't drop it. We also assert that the connection is valid. let connection = { let result = - unsafe { XCBConnection::from_raw_xcb_connection(xcb_handle.connection, false) }; + unsafe { XCBConnection::from_raw_xcb_connection(connection.as_ptr(), false) }; result.swbuf_err("Failed to wrap XCB connection")? }; @@ -172,13 +174,16 @@ impl X11Impl { /// Create a new `X11Impl` from a `HasWindowHandle`. pub(crate) fn new(window_src: W, display: Rc>) -> Result> { // Get the underlying raw window handle. - let raw = window_src.window_handle()?.raw_window_handle()?; + let raw = window_src.window_handle()?.as_raw(); let window_handle = match raw { RawWindowHandle::Xcb(xcb) => xcb, RawWindowHandle::Xlib(xlib) => { - let mut xcb_window_handle = XcbWindowHandle::empty(); - xcb_window_handle.window = xlib.window as _; - xcb_window_handle.visual_id = xlib.visual_id as _; + let window = match NonZeroU32::new(xlib.window as u32) { + Some(window) => window, + None => return Err(SoftBufferError::IncompleteWindowHandle.into()), + }; + let mut xcb_window_handle = XcbWindowHandle::new(window); + xcb_window_handle.visual_id = NonZeroU32::new(xlib.visual_id as u32); xcb_window_handle } _ => { @@ -187,13 +192,7 @@ impl X11Impl { }; log::trace!("new: window_handle={:X}", window_handle.window); - - // Check that the handle is valid. - if window_handle.window == 0 { - return Err(SoftBufferError::IncompleteWindowHandle.into()); - } - - let window = window_handle.window; + let window = window_handle.window.get(); // Run in parallel: start getting the window depth and (if necessary) visual. let display2 = display.clone(); @@ -202,7 +201,7 @@ impl X11Impl { .connection() .get_geometry(window) .swbuf_err("Failed to send geometry request")?; - let window_attrs_token = if window_handle.visual_id == 0 { + let window_attrs_token = if window_handle.visual_id.is_none() { Some( display2 .connection() @@ -239,7 +238,7 @@ impl X11Impl { .reply() .swbuf_err("Failed to get geometry reply")?; let visual_id = match window_attrs_token { - None => window_handle.visual_id, + None => window_handle.visual_id.unwrap().get(), Some(window_attrs) => { window_attrs .reply()