#[cfg(ffi_xcb_shm··)]
use crate::XShmBuffer;
use crate::{XCpuBuffer, XDisplay, XError, XImageMode, XImageStore, XWindow};
#[doc = crate::_tags!(unix runtime)]
#[doc = crate::_doc_meta!{location("sys/device/display/x11")}]
#[derive(Debug)]
pub(crate) struct XSurface {
width: u16,
height: u16,
depth: u8,
storage: XSurfaceStorage,
}
impl XSurface {
fn _new(width: u16, height: u16, depth: u8, storage: XSurfaceStorage) -> Self {
Self { width, height, depth, storage }
}
pub fn new(display: &XDisplay, width: u16, height: u16, depth: u8) -> Result<Self, XError> {
#[cfg(not(ffi_xcb_shm··))]
return Self::new_cpu(display, width, height, depth);
#[cfg(ffi_xcb_shm··)]
match XShmBuffer::new(display, width, height, depth) {
Ok(shm) => Ok(Self::_new(width, height, depth, XSurfaceStorage::Shm(shm))),
Err(XError::ExtensionUnavailable(_)) => Self::new_cpu(display, width, height, depth),
Err(err) => Err(err),
}
}
pub fn new_cpu(display: &XDisplay, width: u16, height: u16, depth: u8) -> Result<Self, XError> {
let cpu = XCpuBuffer::new(display, width, height, depth)?;
Ok(Self::_new(width, height, depth, XSurfaceStorage::Cpu(cpu)))
}
#[cfg(ffi_xcb_shm··)]
pub fn new_shm(display: &XDisplay, width: u16, height: u16, depth: u8) -> Result<Self, XError> {
let shm = XShmBuffer::new(display, width, height, depth)?;
Ok(Self::_new(width, height, depth, XSurfaceStorage::Shm(shm)))
}
pub fn present(&self, display: &mut XDisplay, window: &XWindow) -> Result<(), XError> {
self.storage.present(display, window, self.width, self.height, self.depth)
}
pub const fn mode(&self) -> XImageMode {
match self.storage {
XSurfaceStorage::Cpu(_) => XImageMode::Cpu,
#[cfg(ffi_xcb_shm··)]
XSurfaceStorage::Shm(_) => XImageMode::Shm,
}
}
}
#[rustfmt::skip]
impl XImageStore for XSurface {
fn size(&self) -> (u16, u16) { (self.width, self.height) }
fn depth(&self) -> u8 { self.depth }
fn bytes(&self) -> &[u8] { self.storage.bytes() }
fn bytes_mut(&mut self) -> &mut [u8] { self.storage.bytes_mut() }
fn resize(&mut self, display: &XDisplay, width: u16, height: u16, depth: u8)
-> Result<(), XError> {
self.storage.resize(display, width, height, depth)
}
}
#[doc = crate::_tags!(unix runtime)]
#[doc = crate::_doc_meta!{
location("sys/device/display/x11"),
#[cfg(target_pointer_width = "64")]
test_size_of(__: XSurfaceFrame<'_> = 16|128; niche Option),
}]
pub struct XSurfaceFrame<'a> {
surface: &'a mut XSurface,
bytes_per_line: u32,
}
#[rustfmt::skip]
impl<'a> XSurfaceFrame<'a> {
pub(crate) const fn _new(surface: &'a mut XSurface, bytes_per_line: u32) -> Self {
Self { surface, bytes_per_line }
}
#[must_use]
pub const fn width(&self) -> u16 { self.surface.width }
#[must_use]
pub const fn height(&self) -> u16 { self.surface.height }
#[must_use]
pub const fn depth(&self) -> u8 { self.surface.depth }
#[must_use]
pub const fn bytes_per_line(&self) -> u32 { self.bytes_per_line }
pub const fn mode(&self) -> XImageMode { self.surface.mode() }
#[must_use]
pub const fn is_tight_rows(&self) -> bool {
let bits = self.width() as u32 * self.depth() as u32;
bits.div_ceil(8) == self.bytes_per_line
}
pub fn bytes_mut(&mut self) -> &mut [u8] { self.surface.bytes_mut() }
}
#[derive(Debug)]
enum XSurfaceStorage {
Cpu(XCpuBuffer),
#[cfg(ffi_xcb_shm··)]
Shm(XShmBuffer),
}
#[rustfmt::skip]
impl XSurfaceStorage {
#[allow(unused_variables, reason = "display gated by ffi_xcb_shm··")]
pub fn present(&self, display: &mut XDisplay, window: &XWindow,
width: u16, height: u16, depth: u8) -> Result<(), XError> {
match self {
Self::Cpu(cpu) => {
window.put_image_bytes(width, height, depth, cpu.bytes());
Ok(())
}
#[cfg(ffi_xcb_shm··)]
Self::Shm(shm) => shm.present(display, window),
}
}
}
impl XImageStore for XSurfaceStorage {
fn size(&self) -> (u16, u16) {
match self {
Self::Cpu(cpu) => cpu.size(),
#[cfg(ffi_xcb_shm··)]
Self::Shm(shm) => shm.size(),
}
}
fn depth(&self) -> u8 {
match self {
Self::Cpu(cpu) => cpu.depth(),
#[cfg(ffi_xcb_shm··)]
Self::Shm(shm) => shm.depth(),
}
}
fn bytes(&self) -> &[u8] {
match self {
Self::Cpu(cpu) => cpu.bytes(),
#[cfg(ffi_xcb_shm··)]
Self::Shm(shm) => shm.bytes(),
}
}
fn bytes_mut(&mut self) -> &mut [u8] {
match self {
Self::Cpu(cpu) => cpu.bytes_mut(),
#[cfg(ffi_xcb_shm··)]
Self::Shm(shm) => shm.bytes_mut(),
}
}
fn resize(
&mut self,
display: &XDisplay,
width: u16,
height: u16,
depth: u8,
) -> Result<(), XError> {
match self {
Self::Cpu(cpu) => cpu.resize(display, width, height, depth),
#[cfg(ffi_xcb_shm··)]
Self::Shm(shm) => shm.resize(display, width, height, depth),
}
}
}