Skip to content

Commit

Permalink
Added ability to tell backend that you want to use transparency/alpha…
Browse files Browse the repository at this point in the history
… channel

Created RGBX/RGBA structs that can be used on every platform without needing to think about how the platform stores the u32 as the conversion to each of the platforms happens automatically
  • Loading branch information
jaysonmaw committed Sep 10, 2024
1 parent ad3bd6d commit d616099
Show file tree
Hide file tree
Showing 8 changed files with 693 additions and 72 deletions.
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ name = "buffer_mut"
harness = false

[features]
default = ["kms", "x11", "x11-dlopen", "wayland", "wayland-dlopen"]
default = ["kms", "x11", "x11-dlopen", "wayland", "wayland-dlopen","compatibility"]
kms = ["bytemuck", "drm", "rustix"]
wayland = ["wayland-backend", "wayland-client", "wayland-sys", "memmap2", "rustix", "fastrand"]
wayland-dlopen = ["wayland-sys/dlopen"]
x11 = ["as-raw-xcb-connection", "bytemuck", "fastrand", "rustix", "tiny-xlib", "x11rb"]
x11-dlopen = ["tiny-xlib/dlopen", "x11rb/dl-libxcb"]
compatibility = []

[dependencies]
log = "0.4.17"
raw_window_handle = { package = "raw-window-handle", version = "0.6", features = ["std"] }
num = "0.4.3"
duplicate = "1.0.0"

[target.'cfg(all(unix, not(any(target_vendor = "apple", target_os = "android", target_os = "redox"))))'.dependencies]
as-raw-xcb-connection = { version = "1.0.0", optional = true }
Expand All @@ -43,7 +46,7 @@ x11rb = { version = "0.13.0", features = ["allow-unsafe-code", "shm"], optional

[target.'cfg(target_os = "windows")'.dependencies.windows-sys]
version = "0.59.0"
features = ["Win32_Graphics_Gdi", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging", "Win32_Foundation"]
features = ["Win32_Graphics_Gdi", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging", "Win32_Foundation", "Win32_UI_ColorSystem"]

[target.'cfg(target_vendor = "apple")'.dependencies]
bytemuck = { version = "1.12.3", features = ["extern_crate_alloc"] }
Expand Down
2 changes: 1 addition & 1 deletion benches/buffer_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn buffer_mut(c: &mut Criterion) {
let mut buffer = surface.buffer_mut().unwrap();
b.iter(|| {
for _ in 0..500 {
let x: &mut [u32] = &mut buffer;
let x: &mut [u32] = &mut buffer.pixels_mut();
black_box(x);
}
});
Expand Down
109 changes: 83 additions & 26 deletions src/backend_dispatch.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
//! Implements `buffer_interface::*` traits for enums dispatching to backends
use crate::{backend_interface::*, backends, InitError, Rect, SoftBufferError};
use crate::{backend_interface::*, backends, InitError, Rect, SoftBufferError, BufferReturn, WithAlpha, WithoutAlpha};

use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
use duplicate::duplicate_item;
use std::num::NonZeroU32;
#[cfg(any(wayland_platform, x11_platform, kms_platform))]
use std::sync::Arc;

/// A macro for creating the enum used to statically dispatch to the platform-specific implementation.
macro_rules! make_dispatch {
macro_rules! make_enum {
(
<$dgen: ident, $wgen: ident> =>
<$dgen: ident, $wgen: ident, $alpha: ident> =>
$(
$(#[$attr:meta])*
$name: ident
Expand All @@ -24,6 +25,21 @@ macro_rules! make_dispatch {
)*
}

#[allow(clippy::large_enum_variant)] // it's boxed anyways
pub(crate) enum SurfaceDispatch<$dgen, $wgen, $alpha> {
$(
$(#[$attr])*
$name($surface_inner),
)*
}

pub(crate) enum BufferDispatch<'a, $dgen, $wgen, $alpha> {
$(
$(#[$attr])*
$name($buffer_inner),
)*
}

impl<D: HasDisplayHandle> ContextDispatch<D> {
pub fn variant_name(&self) -> &'static str {
match self {
Expand Down Expand Up @@ -54,18 +70,21 @@ macro_rules! make_dispatch {
Err(InitError::Unsupported(display))
}
}
};
}

#[allow(clippy::large_enum_variant)] // it's boxed anyways
pub(crate) enum SurfaceDispatch<$dgen, $wgen> {
$(
$(#[$attr])*
$name($surface_inner),
)*
}

impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for SurfaceDispatch<D, W> {
macro_rules! make_dispatch {
(
<$dgen: ident, $wgen: ident, $alpha: ident> =>
$(
$(#[$attr:meta])*
$name: ident
($context_inner: ty, $surface_inner: ty, $buffer_inner: ty),
)*
) => {
impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W, $alpha> for SurfaceDispatch<D, W, $alpha>{
type Context = ContextDispatch<D>;
type Buffer<'a> = BufferDispatch<'a, D, W> where Self: 'a;
type Buffer<'a> = BufferDispatch<'a, D, W, $alpha> where Self: 'a;

fn new(window: W, display: &Self::Context) -> Result<Self, InitError<W>>
where
Expand All @@ -79,6 +98,18 @@ macro_rules! make_dispatch {
}
}

fn new_with_alpha(window: W, display: &Self::Context) -> Result<Self, InitError<W>>
where
W: Sized,
Self: Sized {
match display {
$(
$(#[$attr])*
ContextDispatch::$name(inner) => Ok(Self::$name(<$surface_inner>::new_with_alpha(window, inner)?)),
)*
}
}

fn window(&self) -> &W {
match self {
$(
Expand All @@ -97,7 +128,7 @@ macro_rules! make_dispatch {
}
}

fn buffer_mut(&mut self) -> Result<BufferDispatch<'_, D, W>, SoftBufferError> {
fn buffer_mut(&mut self) -> Result<BufferDispatch<'_, D, W, $alpha>, SoftBufferError> {
match self {
$(
$(#[$attr])*
Expand All @@ -116,14 +147,8 @@ macro_rules! make_dispatch {
}
}

pub(crate) enum BufferDispatch<'a, $dgen, $wgen> {
$(
$(#[$attr])*
$name($buffer_inner),
)*
}

impl<'a, D: HasDisplayHandle, W: HasWindowHandle> BufferInterface for BufferDispatch<'a, D, W> {

impl<'a, D: HasDisplayHandle, W: HasWindowHandle> BufferInterface<$alpha> for BufferDispatch<'a, D, W, $alpha> {
#[inline]
fn pixels(&self) -> &[u32] {
match self {
Expand All @@ -144,6 +169,15 @@ macro_rules! make_dispatch {
}
}

fn pixels_rgb_mut(&mut self) -> &mut[<$alpha as BufferReturn>::Output]{
match self {
$(
$(#[$attr])*
Self::$name(inner) => inner.pixels_rgb_mut(),
)*
}
}

fn age(&self) -> u8 {
match self {
$(
Expand Down Expand Up @@ -176,20 +210,43 @@ macro_rules! make_dispatch {

// XXX empty enum with generic bound is invalid?

make_dispatch! {
<D, W> =>
make_enum!{
<D, W, A> =>
#[cfg(x11_platform)]
X11(Arc<backends::x11::X11DisplayImpl<D>>, backends::x11::X11Impl<D, W>, backends::x11::BufferImpl<'a, D, W>),
#[cfg(wayland_platform)]
Wayland(Arc<backends::wayland::WaylandDisplayImpl<D>>, backends::wayland::WaylandImpl<D, W>, backends::wayland::BufferImpl<'a, D, W>),
#[cfg(kms_platform)]
Kms(Arc<backends::kms::KmsDisplayImpl<D>>, backends::kms::KmsImpl<D, W>, backends::kms::BufferImpl<'a, D, W>),
#[cfg(target_os = "windows")]
Win32(D, backends::win32::Win32Impl<D, W>, backends::win32::BufferImpl<'a, D, W>),
Win32(D, backends::win32::Win32Impl<D, W, A>, backends::win32::BufferImpl<'a, D, W, A>),
#[cfg(target_vendor = "apple")]
CoreGraphics(D, backends::cg::CGImpl<D, W>, backends::cg::BufferImpl<'a, D, W>),
CoreGraphics(D, backends::cg::CGImpl<D, W, A>, backends::cg::BufferImpl<'a, D, W, A>),
#[cfg(target_arch = "wasm32")]
Web(backends::web::WebDisplayImpl<D>, backends::web::WebImpl<D, W>, backends::web::BufferImpl<'a, D, W>),
#[cfg(target_os = "redox")]
Orbital(D, backends::orbital::OrbitalImpl<D, W>, backends::orbital::BufferImpl<'a, D, W>),
}

#[duplicate_item(
TY;
[ WithAlpha ];
[ WithoutAlpha ];
)]
make_dispatch! {
<D, W, TY> =>
#[cfg(x11_platform)]
X11(Arc<backends::x11::X11DisplayImpl<D>>, backends::x11::X11Impl<D, W>, backends::x11::BufferImpl<'a, D, W>),
#[cfg(wayland_platform)]
Wayland(Arc<backends::wayland::WaylandDisplayImpl<D>>, backends::wayland::WaylandImpl<D, W>, backends::wayland::BufferImpl<'a, D, W>),
#[cfg(kms_platform)]
Kms(Arc<backends::kms::KmsDisplayImpl<D>>, backends::kms::KmsImpl<D, W>, backends::kms::BufferImpl<'a, D, W>),
#[cfg(target_os = "windows")]
Win32(D, backends::win32::Win32Impl<D, W, TY>, backends::win32::BufferImpl<'a, D, W, TY>),
#[cfg(target_vendor = "apple")]
CoreGraphics(D, backends::cg::CGImpl<D, W, TY>, backends::cg::BufferImpl<'a, D, W, TY>),
#[cfg(target_arch = "wasm32")]
Web(backends::web::WebDisplayImpl<D>, backends::web::WebImpl<D, W>, backends::web::BufferImpl<'a, D, W>),
#[cfg(target_os = "redox")]
Orbital(D, backends::orbital::OrbitalImpl<D, W>, backends::orbital::BufferImpl<'a, D, W>),
}
Loading

0 comments on commit d616099

Please sign in to comment.