commit
df091d59dd
7 changed files with 75 additions and 49 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{GraphicsContextImpl, SwBufError};
|
use crate::SwBufError;
|
||||||
use raw_window_handle::AppKitWindowHandle;
|
use raw_window_handle::AppKitWindowHandle;
|
||||||
use core_graphics::base::{kCGBitmapByteOrder32Little, kCGImageAlphaNoneSkipFirst, kCGRenderingIntentDefault};
|
use core_graphics::base::{kCGBitmapByteOrder32Little, kCGImageAlphaNoneSkipFirst, kCGRenderingIntentDefault};
|
||||||
use core_graphics::color_space::CGColorSpace;
|
use core_graphics::color_space::CGColorSpace;
|
||||||
|
|
@ -32,10 +32,8 @@ impl CGImpl {
|
||||||
let _: () = msg_send![subview, release]; // releases subview (-1) = 1
|
let _: () = msg_send![subview, release]; // releases subview (-1) = 1
|
||||||
Ok(Self{layer})
|
Ok(Self{layer})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl GraphicsContextImpl for CGImpl {
|
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
||||||
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 = std::slice::from_raw_parts(
|
let data = std::slice::from_raw_parts(
|
||||||
buffer.as_ptr() as *const u8,
|
buffer.as_ptr() as *const u8,
|
||||||
|
|
|
||||||
69
src/lib.rs
69
src/lib.rs
|
|
@ -27,7 +27,54 @@ use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandl
|
||||||
/// An instance of this struct contains the platform-specific data that must be managed in order to
|
/// An instance of this struct contains the platform-specific data that must be managed in order to
|
||||||
/// write to a window on that platform.
|
/// write to a window on that platform.
|
||||||
pub struct GraphicsContext {
|
pub struct GraphicsContext {
|
||||||
graphics_context_impl: Box<dyn GraphicsContextImpl>,
|
/// The inner static dispatch object.
|
||||||
|
///
|
||||||
|
/// This is boxed so that `GraphicsContext` is the same size on every platform, which should
|
||||||
|
/// hopefully prevent surprises.
|
||||||
|
graphics_context_impl: Box<Dispatch>
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A macro for creating the enum used to statically dispatch to the platform-specific implementation.
|
||||||
|
macro_rules! make_dispatch {
|
||||||
|
(
|
||||||
|
$(
|
||||||
|
$(#[$attr:meta])*
|
||||||
|
$name: ident ($inner_ty: ty),
|
||||||
|
)*
|
||||||
|
) => {
|
||||||
|
enum Dispatch {
|
||||||
|
$(
|
||||||
|
$(#[$attr])*
|
||||||
|
$name($inner_ty),
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dispatch {
|
||||||
|
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
||||||
|
match self {
|
||||||
|
$(
|
||||||
|
$(#[$attr])*
|
||||||
|
Self::$name(inner) => inner.set_buffer(buffer, width, height),
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
make_dispatch! {
|
||||||
|
#[cfg(all(feature = "x11", any(target_os = "linux", target_os = "freebsd")))]
|
||||||
|
X11(x11::X11Impl),
|
||||||
|
#[cfg(all(feature = "wayland", any(target_os = "linux", target_os = "freebsd")))]
|
||||||
|
Wayland(wayland::WaylandImpl),
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
Win32(win32::Win32Impl),
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
CG(cg::CGImpl),
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
Web(web::WebImpl),
|
||||||
|
#[cfg(target_os = "redox")]
|
||||||
|
Orbital(orbital::OrbitalImpl),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GraphicsContext {
|
impl GraphicsContext {
|
||||||
|
|
@ -48,19 +95,19 @@ impl GraphicsContext {
|
||||||
/// - Ensure that the provided handles are valid to draw a 2D buffer to, and are valid for the
|
/// - Ensure that the provided handles are valid to draw a 2D buffer to, and are valid for the
|
||||||
/// lifetime of the GraphicsContext
|
/// lifetime of the GraphicsContext
|
||||||
pub unsafe fn from_raw(raw_window_handle: RawWindowHandle, raw_display_handle: RawDisplayHandle) -> Result<Self, SwBufError> {
|
pub unsafe fn from_raw(raw_window_handle: RawWindowHandle, raw_display_handle: RawDisplayHandle) -> Result<Self, SwBufError> {
|
||||||
let imple: Box<dyn GraphicsContextImpl> = match (raw_window_handle, raw_display_handle) {
|
let imple: Dispatch = match (raw_window_handle, raw_display_handle) {
|
||||||
#[cfg(all(feature = "x11", any(target_os = "linux", target_os = "freebsd")))]
|
#[cfg(all(feature = "x11", any(target_os = "linux", target_os = "freebsd")))]
|
||||||
(RawWindowHandle::Xlib(xlib_window_handle), RawDisplayHandle::Xlib(xlib_display_handle)) => Box::new(x11::X11Impl::new(xlib_window_handle, xlib_display_handle)?),
|
(RawWindowHandle::Xlib(xlib_window_handle), RawDisplayHandle::Xlib(xlib_display_handle)) => Dispatch::X11(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), RawDisplayHandle::Wayland(wayland_display_handle)) => Box::new(wayland::WaylandImpl::new(wayland_window_handle, wayland_display_handle)?),
|
(RawWindowHandle::Wayland(wayland_window_handle), RawDisplayHandle::Wayland(wayland_display_handle)) => Dispatch::Wayland(wayland::WaylandImpl::new(wayland_window_handle, wayland_display_handle)?),
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
(RawWindowHandle::Win32(win32_handle), _) => Box::new(win32::Win32Impl::new(&win32_handle)?),
|
(RawWindowHandle::Win32(win32_handle), _) => Dispatch::Win32(win32::Win32Impl::new(&win32_handle)?),
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
(RawWindowHandle::AppKit(appkit_handle), _) => Box::new(cg::CGImpl::new(appkit_handle)?),
|
(RawWindowHandle::AppKit(appkit_handle), _) => Dispatch::CG(cg::CGImpl::new(appkit_handle)?),
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
(RawWindowHandle::Web(web_handle), _) => Box::new(web::WebImpl::new(web_handle)?),
|
(RawWindowHandle::Web(web_handle), _) => Dispatch::Web(web::WebImpl::new(web_handle)?),
|
||||||
#[cfg(target_os = "redox")]
|
#[cfg(target_os = "redox")]
|
||||||
(RawWindowHandle::Orbital(orbital_handle), _) => Box::new(orbital::OrbitalImpl::new(orbital_handle)?),
|
(RawWindowHandle::Orbital(orbital_handle), _) => Dispatch::Orbital(orbital::OrbitalImpl::new(orbital_handle)?),
|
||||||
(unimplemented_window_handle, unimplemented_display_handle) => return Err(SwBufError::UnsupportedPlatform {
|
(unimplemented_window_handle, unimplemented_display_handle) => return Err(SwBufError::UnsupportedPlatform {
|
||||||
human_readable_window_platform_name: window_handle_type_name(&unimplemented_window_handle),
|
human_readable_window_platform_name: window_handle_type_name(&unimplemented_window_handle),
|
||||||
human_readable_display_platform_name: display_handle_type_name(&unimplemented_display_handle),
|
human_readable_display_platform_name: display_handle_type_name(&unimplemented_display_handle),
|
||||||
|
|
@ -70,7 +117,7 @@ impl GraphicsContext {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
graphics_context_impl: imple,
|
graphics_context_impl: Box::new(imple)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,10 +156,6 @@ impl GraphicsContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait GraphicsContextImpl {
|
|
||||||
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn window_handle_type_name(handle: &RawWindowHandle) -> &'static str {
|
fn window_handle_type_name(handle: &RawWindowHandle) -> &'static str {
|
||||||
match handle {
|
match handle {
|
||||||
RawWindowHandle::Xlib(_) => "Xlib",
|
RawWindowHandle::Xlib(_) => "Xlib",
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ use std::{
|
||||||
str,
|
str,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::GraphicsContextImpl;
|
|
||||||
use crate::SwBufError;
|
use crate::SwBufError;
|
||||||
|
|
||||||
struct OrbitalMap {
|
struct OrbitalMap {
|
||||||
|
|
@ -49,10 +48,8 @@ impl OrbitalImpl {
|
||||||
pub fn new(handle: OrbitalWindowHandle) -> Result<Self, SwBufError> {
|
pub fn new(handle: OrbitalWindowHandle) -> Result<Self, SwBufError> {
|
||||||
Ok(Self { handle })
|
Ok(Self { handle })
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl GraphicsContextImpl for OrbitalImpl {
|
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width_u16: u16, height_u16: u16) {
|
||||||
unsafe fn set_buffer(&mut self, buffer: &[u32], width_u16: u16, height_u16: u16) {
|
|
||||||
let window_fd = self.handle.window as usize;
|
let window_fd = self.handle.window as usize;
|
||||||
|
|
||||||
// Read the current width and size
|
// Read the current width and size
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{error::unwrap, GraphicsContextImpl, SwBufError};
|
use crate::{error::unwrap, SwBufError};
|
||||||
use raw_window_handle::{WaylandDisplayHandle, WaylandWindowHandle};
|
use raw_window_handle::{WaylandDisplayHandle, WaylandWindowHandle};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use wayland_client::{
|
use wayland_client::{
|
||||||
|
|
@ -78,10 +78,8 @@ impl WaylandImpl {
|
||||||
self.buffers.push_back(buffer);
|
self.buffers.push_back(buffer);
|
||||||
self.buffers.back().unwrap()
|
self.buffers.back().unwrap()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl GraphicsContextImpl for WaylandImpl {
|
pub(super) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
||||||
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
|
||||||
let _ = self.event_queue.dispatch_pending(&mut State);
|
let _ = self.event_queue.dispatch_pending(&mut State);
|
||||||
|
|
||||||
let surface = self.surface.clone();
|
let surface = self.surface.clone();
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ use web_sys::CanvasRenderingContext2d;
|
||||||
use web_sys::HtmlCanvasElement;
|
use web_sys::HtmlCanvasElement;
|
||||||
use web_sys::ImageData;
|
use web_sys::ImageData;
|
||||||
|
|
||||||
use crate::GraphicsContextImpl;
|
|
||||||
use crate::SwBufError;
|
use crate::SwBufError;
|
||||||
|
|
||||||
pub struct WebImpl {
|
pub struct WebImpl {
|
||||||
|
|
@ -60,10 +59,8 @@ impl WebImpl {
|
||||||
|
|
||||||
Ok(Self { canvas, ctx })
|
Ok(Self { canvas, ctx })
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl GraphicsContextImpl for WebImpl {
|
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
||||||
unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
|
||||||
self.canvas.set_width(width.into());
|
self.canvas.set_width(width.into());
|
||||||
self.canvas.set_height(height.into());
|
self.canvas.set_height(height.into());
|
||||||
|
|
||||||
|
|
|
||||||
21
src/win32.rs
21
src/win32.rs
|
|
@ -1,12 +1,12 @@
|
||||||
//! Implementation of software buffering for Windows.
|
//! Implementation of software buffering for Windows.
|
||||||
//!
|
//!
|
||||||
//! This module converts the input buffer into a bitmap and then stretches it to the window.
|
//! This module converts the input buffer into a bitmap and then stretches it to the window.
|
||||||
|
|
||||||
use crate::{GraphicsContextImpl, SwBufError};
|
use crate::SwBufError;
|
||||||
use raw_window_handle::Win32WindowHandle;
|
use raw_window_handle::Win32WindowHandle;
|
||||||
|
|
||||||
use std::mem;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::mem;
|
||||||
use std::os::raw::c_int;
|
use std::os::raw::c_int;
|
||||||
|
|
||||||
use windows_sys::Win32::Foundation::HWND;
|
use windows_sys::Win32::Foundation::HWND;
|
||||||
|
|
@ -33,9 +33,9 @@ struct BitmapInfo {
|
||||||
|
|
||||||
impl Win32Impl {
|
impl Win32Impl {
|
||||||
/// Create a new `Win32Impl` from a `Win32WindowHandle`.
|
/// Create a new `Win32Impl` from a `Win32WindowHandle`.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The `Win32WindowHandle` must be a valid window handle.
|
/// The `Win32WindowHandle` must be a valid window handle.
|
||||||
pub unsafe fn new(handle: &Win32WindowHandle) -> Result<Self, crate::SwBufError> {
|
pub unsafe fn new(handle: &Win32WindowHandle) -> Result<Self, crate::SwBufError> {
|
||||||
// It is valid for the window handle to be null here. Error out if it is.
|
// It is valid for the window handle to be null here. Error out if it is.
|
||||||
|
|
@ -56,17 +56,12 @@ impl Win32Impl {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self { dc, window: hwnd })
|
||||||
dc,
|
|
||||||
window: hwnd,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl GraphicsContextImpl for Win32Impl {
|
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
||||||
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 = 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;
|
||||||
|
|
|
||||||
12
src/x11.rs
12
src/x11.rs
|
|
@ -1,10 +1,10 @@
|
||||||
//! Implementation of software buffering for X11.
|
//! Implementation of software buffering for X11.
|
||||||
//!
|
//!
|
||||||
//! This module converts the input buffer into an XImage and then sends it over the wire to be
|
//! This module converts the input buffer into an XImage and then sends it over the wire to be
|
||||||
//! drawn. A more effective implementation would use shared memory instead of the wire. In
|
//! drawn. A more effective implementation would use shared memory instead of the wire. In
|
||||||
//! addition, we may also want to blit to a pixmap instead of a window.
|
//! addition, we may also want to blit to a pixmap instead of a window.
|
||||||
|
|
||||||
use crate::{GraphicsContextImpl, SwBufError};
|
use crate::SwBufError;
|
||||||
use raw_window_handle::{XlibDisplayHandle, XlibWindowHandle};
|
use raw_window_handle::{XlibDisplayHandle, XlibWindowHandle};
|
||||||
use std::os::raw::{c_char, c_uint};
|
use std::os::raw::{c_char, c_uint};
|
||||||
use x11_dl::xlib::{Display, Visual, Xlib, ZPixmap, GC};
|
use x11_dl::xlib::{Display, Visual, Xlib, ZPixmap, GC};
|
||||||
|
|
@ -32,9 +32,9 @@ pub struct X11Impl {
|
||||||
|
|
||||||
impl X11Impl {
|
impl X11Impl {
|
||||||
/// Create a new `X11Impl` from a `XlibWindowHandle` and `XlibDisplayHandle`.
|
/// Create a new `X11Impl` from a `XlibWindowHandle` and `XlibDisplayHandle`.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The `XlibWindowHandle` and `XlibDisplayHandle` must be valid.
|
/// The `XlibWindowHandle` and `XlibDisplayHandle` must be valid.
|
||||||
pub unsafe fn new(
|
pub unsafe fn new(
|
||||||
window_handle: XlibWindowHandle,
|
window_handle: XlibWindowHandle,
|
||||||
|
|
@ -83,10 +83,8 @@ impl X11Impl {
|
||||||
depth,
|
depth,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl GraphicsContextImpl for X11Impl {
|
pub(crate) unsafe fn set_buffer(&mut self, buffer: &[u32], width: u16, height: u16) {
|
||||||
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 = (self.lib.XCreateImage)(
|
||||||
self.display_handle.display as *mut Display,
|
self.display_handle.display as *mut Display,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue