Skip to content

Commit

Permalink
Reimplement dumbbuffer
Browse files Browse the repository at this point in the history
  • Loading branch information
Drakulix committed May 12, 2019
1 parent 3038525 commit 7ee9556
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 93 deletions.
102 changes: 9 additions & 93 deletions src/control/dumbbuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,106 +4,22 @@
//! Memory-supported, slow, but easy & cross-platform buffer implementation
//!

use ffi;
use result::*;
use control;
use buffer;

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
/// Slow, but generic `Buffer` implementation
pub struct DumbBuffer {
size: (u32, u32),
length: usize,
format: buffer::PixelFormat,
pitch: u32,
handle: buffer::Id,
pub(crate) size: (u32, u32),
pub(crate) length: usize,
pub(crate) format: buffer::format::PixelFormat,
pub(crate) pitch: u32,
pub(crate) handle: buffer::Handle,
}

/// Mapping of a dumbbuffer
pub struct DumbMapping<'a> {
_phantom: ::std::marker::PhantomData<&'a ()>,
map: &'a mut [u8],
}

impl DumbBuffer {
/// Create a new dumb buffer with a given size and pixel format
pub fn create_from_device<T>(
device: &T,
size: (u32, u32),
format: buffer::PixelFormat,
) -> Result<Self>
where
T: control::Device,
{
let mut raw: ffi::drm_mode_create_dumb = Default::default();
raw.width = size.0;
raw.height = size.1;
raw.bpp = try!(
format
.bpp()
.ok_or(Error::from_kind(ErrorKind::UnsupportedPixelFormat))
) as u32;

unsafe {
try!(ffi::ioctl_mode_create_dumb(device.as_raw_fd(), &mut raw));
}

let dumb = Self {
size: (raw.width, raw.height),
length: raw.size as usize,
format: format,
pitch: raw.pitch,
handle: buffer::Id::from_raw(raw.handle),
};

Ok(dumb)
}

/// Free the memory resources of a dumb buffer
pub fn destroy<T>(self, device: &T) -> Result<()>
where
T: control::Device,
{
let mut raw: ffi::drm_mode_destroy_dumb = Default::default();
raw.handle = self.handle.as_raw();

unsafe {
try!(ffi::ioctl_mode_destroy_dumb(device.as_raw_fd(), &mut raw));
}

Ok(())
}

/// Map the buffer for access
pub fn map<'a, T>(&'a mut self, device: &T) -> Result<DumbMapping<'a>>
where
T: control::Device,
{
let mut raw: ffi::drm_mode_map_dumb = Default::default();
raw.handle = self.handle.as_raw();

unsafe {
try!(ffi::ioctl_mode_map_dumb(device.as_raw_fd(), &mut raw));
}

let map = {
use nix::sys::mman;
let addr = ::std::ptr::null_mut();
let prot = mman::ProtFlags::PROT_READ | mman::ProtFlags::PROT_WRITE;
let flags = mman::MapFlags::MAP_SHARED;
let length = self.length;
let fd = device.as_raw_fd();
let offset = raw.offset as i64;
unsafe { try!(mman::mmap(addr, length, prot, flags, fd, offset)) }
};

let mapping = DumbMapping {
_phantom: ::std::marker::PhantomData,
map: unsafe { ::std::slice::from_raw_parts_mut(map as *mut _, self.length) },
};

Ok(mapping)
}
pub(crate) _phantom: core::marker::PhantomData<&'a ()>,
pub(crate) map: &'a mut [u8],
}

impl<'a> AsMut<[u8]> for DumbMapping<'a> {
Expand All @@ -126,13 +42,13 @@ impl buffer::Buffer for DumbBuffer {
fn size(&self) -> (u32, u32) {
self.size
}
fn format(&self) -> buffer::PixelFormat {
fn format(&self) -> buffer::format::PixelFormat {
self.format
}
fn pitch(&self) -> u32 {
self.pitch
}
fn handle(&self) -> buffer::Id {
fn handle(&self) -> buffer::Handle {
self.handle
}
}
51 changes: 51 additions & 0 deletions src/control/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use drm_ffi::result::SystemError;

pub mod connector;
pub mod crtc;
pub mod dumbbuffer;
pub mod encoder;
pub mod framebuffer;
pub mod plane;
Expand All @@ -41,6 +42,7 @@ pub mod property;
use std::mem;

use {ResourceType, buffer};
use self::dumbbuffer::*;

/// This trait should be implemented by any object that acts as a DRM device and
/// provides modesetting functionality.
Expand Down Expand Up @@ -387,6 +389,55 @@ pub trait Device: super::Device {
let _info = drm_ffi::gem::close(self.as_raw_fd(), handle.0.get())?;
Ok(())
}

/// Create a new dumb buffer with a given size and pixel format
fn create_dumb_buffer(
&self,
size: (u32, u32),
format: buffer::format::PixelFormat,
) -> Result<DumbBuffer, SystemError> {
let info = drm_ffi::mode::dumbbuffer::create(self.as_raw_fd(), size.0, size.1, format.bpp(), 0)?;

let dumb = DumbBuffer {
size: (info.width, info.height),
length: info.size as usize,
format: format,
pitch: info.pitch,
handle: buffer::Handle(unsafe { core::num::NonZeroU32::new_unchecked(info.handle) }),
};

Ok(dumb)
}

/// Free the memory resources of a dumb buffer
fn destroy_dumb_buffer(&self, buffer: DumbBuffer) -> Result<(), SystemError> {
let _info = drm_ffi::mode::dumbbuffer::destroy(self.as_raw_fd(), buffer.handle.0.get())?;

Ok(())
}

/// Map the buffer for access
fn map_dumb_buffer<'a>(&self, buffer: &'a mut DumbBuffer) -> Result<DumbMapping<'a>, SystemError> {
let info = drm_ffi::mode::dumbbuffer::map(self.as_raw_fd(), buffer.handle.0.get(), 0, 0)?;

let map = {
use ::nix::sys::mman;
let addr = core::ptr::null_mut();
let prot = mman::ProtFlags::PROT_READ | mman::ProtFlags::PROT_WRITE;
let flags = mman::MapFlags::MAP_SHARED;
let length = buffer.length;
let fd = self.as_raw_fd();
let offset = info.offset as i64;
unsafe { mman::mmap(addr, length, prot, flags, fd, offset)? }
};

let mapping = DumbMapping {
_phantom: ::std::marker::PhantomData,
map: unsafe { ::std::slice::from_raw_parts_mut(map as *mut _, buffer.length) },
};

Ok(mapping)
}
}

/// The set of [ResourceHandles](ResourceHandle.t.html) that a
Expand Down

0 comments on commit 7ee9556

Please sign in to comment.