1#![doc = include_str!("../README.md")]
2#![allow(clippy::needless_doctest_main)]
3#![deny(unsafe_op_in_unsafe_fn)]
4#![warn(missing_docs)]
5#![cfg_attr(docsrs, feature(doc_cfg))]
6
7extern crate core;
8
9mod backend_dispatch;
10use backend_dispatch::*;
11mod backend_interface;
12use backend_interface::*;
13mod backends;
14mod error;
15mod util;
16
17use std::cell::Cell;
18use std::marker::PhantomData;
19use std::num::NonZeroU32;
20use std::ops;
21use std::sync::Arc;
22
23use error::InitError;
24pub use error::SoftBufferError;
25
26use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle};
27
28#[cfg(target_family = "wasm")]
29pub use backends::web::SurfaceExtWeb;
30
31#[derive(Clone, Debug)]
34pub struct Context<D> {
35 context_impl: ContextDispatch<D>,
37
38 _marker: PhantomData<Arc<D>>,
40}
41
42impl<D: HasDisplayHandle> Context<D> {
43 pub fn new(display: D) -> Result<Self, SoftBufferError> {
45 match ContextDispatch::new(display) {
46 Ok(context_impl) => Ok(Self {
47 context_impl,
48 _marker: PhantomData,
49 }),
50 Err(InitError::Unsupported(display)) => {
51 let raw = display.display_handle()?.as_raw();
52 Err(SoftBufferError::UnsupportedDisplayPlatform {
53 human_readable_display_platform_name: display_handle_type_name(&raw),
54 display_handle: raw,
55 })
56 }
57 Err(InitError::Failure(f)) => Err(f),
58 }
59 }
60}
61
62#[derive(Clone, Copy, Debug)]
64pub struct Rect {
65 pub x: u32,
67 pub y: u32,
69 pub width: NonZeroU32,
71 pub height: NonZeroU32,
73}
74
75#[derive(Debug)]
77pub struct Surface<D, W> {
78 surface_impl: Box<SurfaceDispatch<D, W>>,
80 _marker: PhantomData<Cell<()>>,
81}
82
83impl<D: HasDisplayHandle, W: HasWindowHandle> Surface<D, W> {
84 pub fn new(context: &Context<D>, window: W) -> Result<Self, SoftBufferError> {
86 match SurfaceDispatch::new(window, &context.context_impl) {
87 Ok(surface_dispatch) => Ok(Self {
88 surface_impl: Box::new(surface_dispatch),
89 _marker: PhantomData,
90 }),
91 Err(InitError::Unsupported(window)) => {
92 let raw = window.window_handle()?.as_raw();
93 Err(SoftBufferError::UnsupportedWindowPlatform {
94 human_readable_window_platform_name: window_handle_type_name(&raw),
95 human_readable_display_platform_name: context.context_impl.variant_name(),
96 window_handle: raw,
97 })
98 }
99 Err(InitError::Failure(f)) => Err(f),
100 }
101 }
102
103 pub fn window(&self) -> &W {
105 self.surface_impl.window()
106 }
107
108 pub fn resize(&mut self, width: NonZeroU32, height: NonZeroU32) -> Result<(), SoftBufferError> {
115 self.surface_impl.resize(width, height)
116 }
117
118 pub fn fetch(&mut self) -> Result<Vec<u32>, SoftBufferError> {
127 self.surface_impl.fetch()
128 }
129
130 pub fn buffer_mut(&mut self) -> Result<Buffer<'_, D, W>, SoftBufferError> {
140 Ok(Buffer {
141 buffer_impl: self.surface_impl.buffer_mut()?,
142 _marker: PhantomData,
143 })
144 }
145}
146
147impl<D: HasDisplayHandle, W: HasWindowHandle> AsRef<W> for Surface<D, W> {
148 #[inline]
149 fn as_ref(&self) -> &W {
150 self.window()
151 }
152}
153
154impl<D: HasDisplayHandle, W: HasWindowHandle> HasWindowHandle for Surface<D, W> {
155 #[inline]
156 fn window_handle(
157 &self,
158 ) -> Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
159 self.window().window_handle()
160 }
161}
162
163#[derive(Debug)]
205pub struct Buffer<'a, D, W> {
206 buffer_impl: BufferDispatch<'a, D, W>,
207 _marker: PhantomData<(Arc<D>, Cell<()>)>,
208}
209
210impl<D: HasDisplayHandle, W: HasWindowHandle> Buffer<'_, D, W> {
211 pub fn width(&self) -> NonZeroU32 {
213 let width = self.buffer_impl.width();
214 debug_assert_eq!(
215 width.get() as usize * self.buffer_impl.height().get() as usize,
216 self.len(),
217 "buffer must be sized correctly"
218 );
219 width
220 }
221
222 pub fn height(&self) -> NonZeroU32 {
224 let height = self.buffer_impl.height();
225 debug_assert_eq!(
226 height.get() as usize * self.buffer_impl.width().get() as usize,
227 self.len(),
228 "buffer must be sized correctly"
229 );
230 height
231 }
232
233 pub fn age(&self) -> u8 {
240 self.buffer_impl.age()
241 }
242
243 pub fn present(self) -> Result<(), SoftBufferError> {
256 self.buffer_impl.present()
257 }
258
259 pub fn present_with_damage(self, damage: &[Rect]) -> Result<(), SoftBufferError> {
271 self.buffer_impl.present_with_damage(damage)
272 }
273}
274
275impl<D: HasDisplayHandle, W: HasWindowHandle> ops::Deref for Buffer<'_, D, W> {
276 type Target = [u32];
277
278 #[inline]
279 fn deref(&self) -> &[u32] {
280 self.buffer_impl.pixels()
281 }
282}
283
284impl<D: HasDisplayHandle, W: HasWindowHandle> ops::DerefMut for Buffer<'_, D, W> {
285 #[inline]
286 fn deref_mut(&mut self) -> &mut [u32] {
287 self.buffer_impl.pixels_mut()
288 }
289}
290
291#[derive(Debug)]
293#[allow(dead_code)]
294pub struct NoDisplayHandle(core::convert::Infallible);
295
296impl HasDisplayHandle for NoDisplayHandle {
297 fn display_handle(
298 &self,
299 ) -> Result<raw_window_handle::DisplayHandle<'_>, raw_window_handle::HandleError> {
300 match self.0 {}
301 }
302}
303
304#[derive(Debug)]
306pub struct NoWindowHandle(());
307
308impl HasWindowHandle for NoWindowHandle {
309 fn window_handle(
310 &self,
311 ) -> Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
312 Err(raw_window_handle::HandleError::NotSupported)
313 }
314}
315
316fn window_handle_type_name(handle: &RawWindowHandle) -> &'static str {
317 match handle {
318 RawWindowHandle::Xlib(_) => "Xlib",
319 RawWindowHandle::Win32(_) => "Win32",
320 RawWindowHandle::WinRt(_) => "WinRt",
321 RawWindowHandle::Web(_) => "Web",
322 RawWindowHandle::Wayland(_) => "Wayland",
323 RawWindowHandle::AndroidNdk(_) => "AndroidNdk",
324 RawWindowHandle::AppKit(_) => "AppKit",
325 RawWindowHandle::Orbital(_) => "Orbital",
326 RawWindowHandle::UiKit(_) => "UiKit",
327 RawWindowHandle::Xcb(_) => "XCB",
328 RawWindowHandle::Drm(_) => "DRM",
329 RawWindowHandle::Gbm(_) => "GBM",
330 RawWindowHandle::Haiku(_) => "Haiku",
331 _ => "Unknown Name", }
333}
334
335fn display_handle_type_name(handle: &RawDisplayHandle) -> &'static str {
336 match handle {
337 RawDisplayHandle::Xlib(_) => "Xlib",
338 RawDisplayHandle::Web(_) => "Web",
339 RawDisplayHandle::Wayland(_) => "Wayland",
340 RawDisplayHandle::AppKit(_) => "AppKit",
341 RawDisplayHandle::Orbital(_) => "Orbital",
342 RawDisplayHandle::UiKit(_) => "UiKit",
343 RawDisplayHandle::Xcb(_) => "XCB",
344 RawDisplayHandle::Drm(_) => "DRM",
345 RawDisplayHandle::Gbm(_) => "GBM",
346 RawDisplayHandle::Haiku(_) => "Haiku",
347 RawDisplayHandle::Windows(_) => "Windows",
348 RawDisplayHandle::Android(_) => "Android",
349 _ => "Unknown Name", }
351}
352
353#[cfg(not(target_family = "wasm"))]
354fn __assert_send() {
355 fn is_send<T: Send>() {}
356 fn is_sync<T: Sync>() {}
357
358 is_send::<Context<()>>();
359 is_sync::<Context<()>>();
360 is_send::<Surface<(), ()>>();
361 is_send::<Buffer<'static, (), ()>>();
362
363 fn __surface_not_sync() {}
370 fn __buffer_not_sync() {}
377}