Use #![deny(unsafe_op_in_unsafe_fn)]
This commit is contained in:
parent
c9e3652d13
commit
89bd260fd8
7 changed files with 109 additions and 90 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
use instant::Instant;
|
use instant::Instant;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::f64::consts::PI;
|
|
||||||
use softbuffer::GraphicsContext;
|
use softbuffer::GraphicsContext;
|
||||||
|
use std::f64::consts::PI;
|
||||||
use winit::event::{Event, WindowEvent};
|
use winit::event::{Event, WindowEvent};
|
||||||
use winit::event_loop::{ControlFlow, EventLoop};
|
use winit::event_loop::{ControlFlow, EventLoop};
|
||||||
use winit::window::WindowBuilder;
|
use winit::window::WindowBuilder;
|
||||||
|
|
|
||||||
23
src/cg.rs
23
src/cg.rs
|
|
@ -23,22 +23,25 @@ impl CGImpl {
|
||||||
let window = handle.ns_window as id;
|
let window = handle.ns_window as id;
|
||||||
let view = handle.ns_view as id;
|
let view = handle.ns_view as id;
|
||||||
let layer = CALayer::new();
|
let layer = CALayer::new();
|
||||||
let subview: id = NSView::alloc(nil).initWithFrame_(NSView::frame(view));
|
unsafe {
|
||||||
layer.set_contents_gravity(ContentsGravity::TopLeft);
|
let subview: id = NSView::alloc(nil).initWithFrame_(NSView::frame(view));
|
||||||
layer.set_needs_display_on_bounds_change(false);
|
layer.set_contents_gravity(ContentsGravity::TopLeft);
|
||||||
layer.set_contents_scale(window.backingScaleFactor());
|
layer.set_needs_display_on_bounds_change(false);
|
||||||
subview.setLayer(layer.id());
|
layer.set_contents_scale(window.backingScaleFactor());
|
||||||
subview.setAutoresizingMask_(NSViewWidthSizable | NSViewHeightSizable);
|
subview.setLayer(layer.id());
|
||||||
|
subview.setAutoresizingMask_(NSViewWidthSizable | NSViewHeightSizable);
|
||||||
|
|
||||||
view.addSubview_(subview); // retains subview (+1) = 2
|
view.addSubview_(subview); // retains subview (+1) = 2
|
||||||
let _: () = msg_send![subview, release]; // releases subview (-1) = 1
|
let _: () = msg_send![subview, release]; // releases subview (-1) = 1
|
||||||
|
}
|
||||||
Ok(Self { layer })
|
Ok(Self { layer })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
||||||
let color_space = CGColorSpace::create_device_rgb();
|
let color_space = CGColorSpace::create_device_rgb();
|
||||||
let data =
|
let data =
|
||||||
std::slice::from_raw_parts(buffer.as_ptr() as *const u8, buffer.len() * 4).to_vec();
|
unsafe { std::slice::from_raw_parts(buffer.as_ptr() as *const u8, buffer.len() * 4) }
|
||||||
|
.to_vec();
|
||||||
let data_provider = CGDataProvider::from_buffer(Arc::new(data));
|
let data_provider = CGDataProvider::from_buffer(Arc::new(data));
|
||||||
let image = CGImage::new(
|
let image = CGImage::new(
|
||||||
width as usize,
|
width as usize,
|
||||||
|
|
@ -52,6 +55,6 @@ impl CGImpl {
|
||||||
false,
|
false,
|
||||||
kCGRenderingIntentDefault,
|
kCGRenderingIntentDefault,
|
||||||
);
|
);
|
||||||
self.layer.set_contents(image.as_ptr() as id);
|
unsafe { self.layer.set_contents(image.as_ptr() as id) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
src/lib.rs
20
src/lib.rs
|
|
@ -1,4 +1,5 @@
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
@ -56,7 +57,7 @@ macro_rules! make_dispatch {
|
||||||
match self {
|
match self {
|
||||||
$(
|
$(
|
||||||
$(#[$attr])*
|
$(#[$attr])*
|
||||||
Self::$name(inner) => inner.set_buffer(buffer, width, height),
|
Self::$name(inner) => unsafe { inner.set_buffer(buffer, width, height) },
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -90,7 +91,7 @@ impl GraphicsContext {
|
||||||
window: &W,
|
window: &W,
|
||||||
display: &D,
|
display: &D,
|
||||||
) -> Result<Self, SwBufError> {
|
) -> Result<Self, SwBufError> {
|
||||||
Self::from_raw(window.raw_window_handle(), display.raw_display_handle())
|
unsafe { Self::from_raw(window.raw_window_handle(), display.raw_display_handle()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new instance of this struct, using the provided raw window and display handles
|
/// Creates a new instance of this struct, using the provided raw window and display handles
|
||||||
|
|
@ -108,22 +109,23 @@ impl GraphicsContext {
|
||||||
(
|
(
|
||||||
RawWindowHandle::Xlib(xlib_window_handle),
|
RawWindowHandle::Xlib(xlib_window_handle),
|
||||||
RawDisplayHandle::Xlib(xlib_display_handle),
|
RawDisplayHandle::Xlib(xlib_display_handle),
|
||||||
) => Dispatch::X11(x11::X11Impl::new(xlib_window_handle, xlib_display_handle)?),
|
) => Dispatch::X11(unsafe {
|
||||||
|
x11::X11Impl::new(xlib_window_handle, xlib_display_handle)?
|
||||||
|
}),
|
||||||
#[cfg(all(feature = "wayland", any(target_os = "linux", target_os = "freebsd")))]
|
#[cfg(all(feature = "wayland", any(target_os = "linux", target_os = "freebsd")))]
|
||||||
(
|
(
|
||||||
RawWindowHandle::Wayland(wayland_window_handle),
|
RawWindowHandle::Wayland(wayland_window_handle),
|
||||||
RawDisplayHandle::Wayland(wayland_display_handle),
|
RawDisplayHandle::Wayland(wayland_display_handle),
|
||||||
) => Dispatch::Wayland(wayland::WaylandImpl::new(
|
) => Dispatch::Wayland(unsafe {
|
||||||
wayland_window_handle,
|
wayland::WaylandImpl::new(wayland_window_handle, wayland_display_handle)?
|
||||||
wayland_display_handle,
|
}),
|
||||||
)?),
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
(RawWindowHandle::Win32(win32_handle), _) => {
|
(RawWindowHandle::Win32(win32_handle), _) => {
|
||||||
Dispatch::Win32(win32::Win32Impl::new(&win32_handle)?)
|
Dispatch::Win32(unsafe { win32::Win32Impl::new(&win32_handle)? })
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
(RawWindowHandle::AppKit(appkit_handle), _) => {
|
(RawWindowHandle::AppKit(appkit_handle), _) => {
|
||||||
Dispatch::CG(cg::CGImpl::new(appkit_handle)?)
|
Dispatch::CG(unsafe { cg::CGImpl::new(appkit_handle)? })
|
||||||
}
|
}
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
(RawWindowHandle::Web(web_handle), _) => Dispatch::Web(web::WebImpl::new(web_handle)?),
|
(RawWindowHandle::Web(web_handle), _) => Dispatch::Web(web::WebImpl::new(web_handle)?),
|
||||||
|
|
|
||||||
|
|
@ -15,15 +15,17 @@ impl OrbitalMap {
|
||||||
let size = pages * syscall::PAGE_SIZE;
|
let size = pages * syscall::PAGE_SIZE;
|
||||||
|
|
||||||
// Map window buffer
|
// Map window buffer
|
||||||
let address = syscall::fmap(
|
let address = unsafe {
|
||||||
fd,
|
syscall::fmap(
|
||||||
&syscall::Map {
|
fd,
|
||||||
offset: 0,
|
&syscall::Map {
|
||||||
size,
|
offset: 0,
|
||||||
flags: syscall::PROT_READ | syscall::PROT_WRITE,
|
size,
|
||||||
address: 0,
|
flags: syscall::PROT_READ | syscall::PROT_WRITE,
|
||||||
},
|
address: 0,
|
||||||
)?;
|
},
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Self { address, size })
|
Ok(Self { address, size })
|
||||||
}
|
}
|
||||||
|
|
@ -69,14 +71,17 @@ impl OrbitalImpl {
|
||||||
|
|
||||||
{
|
{
|
||||||
// Map window buffer
|
// Map window buffer
|
||||||
let window_map = OrbitalMap::new(window_fd, window_width * window_height * 4)
|
let window_map =
|
||||||
.expect("failed to map orbital window");
|
unsafe { OrbitalMap::new(window_fd, window_width * window_height * 4) }
|
||||||
|
.expect("failed to map orbital window");
|
||||||
|
|
||||||
// Window buffer is u32 color data in 0xAABBGGRR format
|
// Window buffer is u32 color data in 0xAABBGGRR format
|
||||||
let window_data = slice::from_raw_parts_mut(
|
let window_data = unsafe {
|
||||||
window_map.address as *mut u32,
|
slice::from_raw_parts_mut(
|
||||||
window_width * window_height,
|
window_map.address as *mut u32,
|
||||||
);
|
window_width * window_height,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
// Copy each line, cropping to fit
|
// Copy each line, cropping to fit
|
||||||
let width = width_u16 as usize;
|
let width = width_u16 as usize;
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@ impl WaylandImpl {
|
||||||
window_handle: WaylandWindowHandle,
|
window_handle: WaylandWindowHandle,
|
||||||
display_handle: WaylandDisplayHandle,
|
display_handle: WaylandDisplayHandle,
|
||||||
) -> Result<Self, SwBufError> {
|
) -> Result<Self, SwBufError> {
|
||||||
let conn = Connection::from_backend(Backend::from_foreign_display(
|
// SAFETY: Ensured by user
|
||||||
display_handle.display as *mut _,
|
let backend = unsafe { Backend::from_foreign_display(display_handle.display as *mut _) };
|
||||||
));
|
let conn = Connection::from_backend(backend);
|
||||||
let (globals, event_queue) = unwrap(
|
let (globals, event_queue) = unwrap(
|
||||||
registry_queue_init(&conn),
|
registry_queue_init(&conn),
|
||||||
"Failed to make round trip to server",
|
"Failed to make round trip to server",
|
||||||
|
|
@ -40,10 +40,12 @@ impl WaylandImpl {
|
||||||
"Failed to instantiate Wayland Shm",
|
"Failed to instantiate Wayland Shm",
|
||||||
)?;
|
)?;
|
||||||
let surface_id = unwrap(
|
let surface_id = unwrap(
|
||||||
ObjectId::from_ptr(
|
unsafe {
|
||||||
wl_surface::WlSurface::interface(),
|
ObjectId::from_ptr(
|
||||||
window_handle.surface as _,
|
wl_surface::WlSurface::interface(),
|
||||||
),
|
window_handle.surface as _,
|
||||||
|
)
|
||||||
|
},
|
||||||
"Failed to create proxy for surface ID.",
|
"Failed to create proxy for surface ID.",
|
||||||
)?;
|
)?;
|
||||||
let surface = unwrap(
|
let surface = unwrap(
|
||||||
|
|
|
||||||
38
src/win32.rs
38
src/win32.rs
|
|
@ -46,7 +46,7 @@ impl Win32Impl {
|
||||||
// Get the handle to the device context.
|
// Get the handle to the device context.
|
||||||
// SAFETY: We have confirmed that the window handle is valid.
|
// SAFETY: We have confirmed that the window handle is valid.
|
||||||
let hwnd = handle.hwnd as HWND;
|
let hwnd = handle.hwnd as HWND;
|
||||||
let dc = GetDC(hwnd);
|
let dc = unsafe { GetDC(hwnd) };
|
||||||
|
|
||||||
// GetDC returns null if there is a platform error.
|
// GetDC returns null if there is a platform error.
|
||||||
if dc == 0 {
|
if dc == 0 {
|
||||||
|
|
@ -61,7 +61,7 @@ impl Win32Impl {
|
||||||
|
|
||||||
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
||||||
// Create a new bitmap info struct.
|
// Create a new bitmap info struct.
|
||||||
let mut bitmap_info: BitmapInfo = mem::zeroed();
|
let mut bitmap_info: BitmapInfo = unsafe { mem::zeroed() };
|
||||||
|
|
||||||
bitmap_info.bmi_header.biSize = mem::size_of::<BITMAPINFOHEADER>() as u32;
|
bitmap_info.bmi_header.biSize = mem::size_of::<BITMAPINFOHEADER>() as u32;
|
||||||
bitmap_info.bmi_header.biPlanes = 1;
|
bitmap_info.bmi_header.biPlanes = 1;
|
||||||
|
|
@ -77,23 +77,25 @@ impl Win32Impl {
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// - The bitmap information is valid.
|
// - The bitmap information is valid.
|
||||||
// - The buffer is a valid pointer to image data.
|
// - The buffer is a valid pointer to image data.
|
||||||
StretchDIBits(
|
unsafe {
|
||||||
self.dc,
|
StretchDIBits(
|
||||||
0,
|
self.dc,
|
||||||
0,
|
0,
|
||||||
width as c_int,
|
0,
|
||||||
height as c_int,
|
width as c_int,
|
||||||
0,
|
height as c_int,
|
||||||
0,
|
0,
|
||||||
width as c_int,
|
0,
|
||||||
height as c_int,
|
width as c_int,
|
||||||
buffer.as_ptr().cast(),
|
height as c_int,
|
||||||
&bitmap_info as *const BitmapInfo as *const _,
|
buffer.as_ptr().cast(),
|
||||||
DIB_RGB_COLORS,
|
&bitmap_info as *const BitmapInfo as *const _,
|
||||||
SRCCOPY,
|
DIB_RGB_COLORS,
|
||||||
);
|
SRCCOPY,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
// Validate the window.
|
// Validate the window.
|
||||||
ValidateRect(self.window, std::ptr::null_mut());
|
unsafe { ValidateRect(self.window, std::ptr::null_mut()) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
65
src/x11.rs
65
src/x11.rs
|
|
@ -65,14 +65,15 @@ impl X11Impl {
|
||||||
// it could mean either screen index zero, or that the screen number was not set. We
|
// it could mean either screen index zero, or that the screen number was not set. We
|
||||||
// can't tell which, so we'll just assume that the screen number was not set.
|
// can't tell which, so we'll just assume that the screen number was not set.
|
||||||
let screen = match display_handle.screen {
|
let screen = match display_handle.screen {
|
||||||
0 => (lib.XDefaultScreen)(display_handle.display as *mut Display),
|
0 => unsafe { (lib.XDefaultScreen)(display_handle.display as *mut Display) },
|
||||||
screen => screen,
|
screen => screen,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use the default graphics context, visual and depth for this screen.
|
// Use the default graphics context, visual and depth for this screen.
|
||||||
let gc = (lib.XDefaultGC)(display_handle.display as *mut Display, screen);
|
let gc = unsafe { (lib.XDefaultGC)(display_handle.display as *mut Display, screen) };
|
||||||
let visual = (lib.XDefaultVisual)(display_handle.display as *mut Display, screen);
|
let visual =
|
||||||
let depth = (lib.XDefaultDepth)(display_handle.display as *mut Display, screen);
|
unsafe { (lib.XDefaultVisual)(display_handle.display as *mut Display, screen) };
|
||||||
|
let depth = unsafe { (lib.XDefaultDepth)(display_handle.display as *mut Display, screen) };
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
window_handle,
|
window_handle,
|
||||||
|
|
@ -86,35 +87,39 @@ impl X11Impl {
|
||||||
|
|
||||||
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
||||||
// Create the image from the buffer.
|
// Create the image from the buffer.
|
||||||
let image = (self.lib.XCreateImage)(
|
let image = unsafe {
|
||||||
self.display_handle.display as *mut Display,
|
(self.lib.XCreateImage)(
|
||||||
self.visual,
|
self.display_handle.display as *mut Display,
|
||||||
self.depth as u32,
|
self.visual,
|
||||||
ZPixmap,
|
self.depth as u32,
|
||||||
0,
|
ZPixmap,
|
||||||
(buffer.as_ptr()) as *mut c_char,
|
0,
|
||||||
width as u32,
|
(buffer.as_ptr()) as *mut c_char,
|
||||||
height as u32,
|
width as u32,
|
||||||
32,
|
height as u32,
|
||||||
(width * 4) as i32,
|
32,
|
||||||
);
|
(width * 4) as i32,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
// Draw the image to the window.
|
// Draw the image to the window.
|
||||||
(self.lib.XPutImage)(
|
unsafe {
|
||||||
self.display_handle.display as *mut Display,
|
(self.lib.XPutImage)(
|
||||||
self.window_handle.window,
|
self.display_handle.display as *mut Display,
|
||||||
self.gc,
|
self.window_handle.window,
|
||||||
image,
|
self.gc,
|
||||||
0,
|
image,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
width as c_uint,
|
0,
|
||||||
height as c_uint,
|
width as c_uint,
|
||||||
);
|
height as c_uint,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
// Delete the image data.
|
// Delete the image data.
|
||||||
(*image).data = std::ptr::null_mut();
|
unsafe { (*image).data = std::ptr::null_mut() };
|
||||||
(self.lib.XDestroyImage)(image);
|
unsafe { (self.lib.XDestroyImage)(image) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue