Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modernize dumbbuffer #33

Merged
merged 7 commits into from
May 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,12 +33,14 @@ use drm_ffi::result::SystemError;

pub mod connector;
pub mod crtc;
pub mod dumbbuffer;
pub mod encoder;
pub mod framebuffer;
pub mod plane;

pub mod property;

use self::dumbbuffer::*;
use buffer;
use std::mem;

Expand Down Expand Up @@ -443,6 +445,55 @@ pub trait Device: super::Device {
let _info = drm_ffi::gem::close(self.as_raw_fd(), handle.into())?;
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: unsafe { mem::transmute(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.into())?;

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.into(), 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
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ extern crate core;

extern crate drm_ffi;

extern crate nix;

pub(crate) mod util;

pub mod control;
Expand Down