use result::*;
use ffi;
use std::ffi::CStr;
use std::hash::{Hash, Hasher};
pub mod connector;
pub mod encoder;
pub mod crtc;
pub mod framebuffer;
pub mod plane;
pub mod property;
pub mod dumbbuffer;
pub type RawHandle = u32;
#[derive(Clone, Copy, PartialEq, Eq, Hash, From, Into)]
pub struct RawName([i8; 32]);
pub trait Device: Sized + super::Device {
fn resource_handles(&self) -> Result<ResourceHandles> {
ResourceHandles::load_from_device(self)
}
fn plane_handles(&self) -> Result<PlaneResourceHandles> {
PlaneResourceHandles::load_from_device(self)
}
fn resource_info<T>(&self, handle: T::Handle) -> Result<T>
where
T: ResourceInfo,
{
T::load_from_device(self, handle)
}
fn set_crtc(
&self,
crtc: crtc::Handle,
fb: framebuffer::Handle,
cons: &[connector::Handle],
position: (u32, u32),
mode: Option<Mode>,
) -> Result<()> {
crtc::set(self, crtc, fb, cons, position, mode)
}
fn create_framebuffer<U>(&self, buffer: &U) -> Result<framebuffer::Info>
where
U: super::buffer::Buffer + ?Sized,
{
framebuffer::create(self, buffer)
}
}
pub trait ResourceHandle: Copy + Eq + Hash + From<RawHandle> + Into<RawHandle> {}
pub trait ResourceInfo: Clone + Eq {
type Handle: ResourceHandle;
fn load_from_device<T>(&T, Self::Handle) -> Result<Self>
where
T: Device;
fn handle(&self) -> Self::Handle;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ResourceHandles {
connectors: ffi::Buffer<connector::Handle>,
encoders: ffi::Buffer<encoder::Handle>,
crtcs: ffi::Buffer<crtc::Handle>,
framebuffers: ffi::Buffer<framebuffer::Handle>,
width: (u32, u32),
height: (u32, u32),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PlaneResourceHandles {
planes: ffi::Buffer<plane::Handle>,
}
impl ResourceHandles {
pub fn load_from_device<T>(device: &T) -> Result<Self>
where
T: Device,
{
let fd = device.as_raw_fd();
let ids = {
let mut raw: ffi::drm_mode_card_res = Default::default();
unsafe { ffi::ioctl_mode_getresources(fd, &mut raw)? };
let ids = ResourceHandles {
connectors: ffi_buf!(raw.connector_id_ptr, raw.count_connectors),
encoders: ffi_buf!(raw.encoder_id_ptr, raw.count_encoders),
crtcs: ffi_buf!(raw.crtc_id_ptr, raw.count_crtcs),
framebuffers: ffi_buf!(raw.fb_id_ptr, raw.count_fbs),
width: (raw.min_width, raw.max_width),
height: (raw.min_height, raw.max_height),
};
unsafe {
try!(ffi::ioctl_mode_getresources(device.as_raw_fd(), &mut raw));
}
ids
};
Ok(ids)
}
pub fn connectors<'a>(&'a self) -> &'a [connector::Handle] {
&self.connectors
}
pub fn encoders<'a>(&'a self) -> &'a [encoder::Handle] {
&self.encoders
}
pub fn crtcs<'a>(&'a self) -> &'a [crtc::Handle] {
&self.crtcs
}
pub fn framebuffers<'a>(&'a self) -> &'a [framebuffer::Handle] {
&self.framebuffers
}
pub fn width(&self) -> (u32, u32) {
(self.width)
}
pub fn height(&self) -> (u32, u32) {
(self.height)
}
pub fn filter_crtcs(&self, filter: CrtcListFilter) -> ffi::Buffer<crtc::Handle> {
self.crtcs
.iter()
.enumerate()
.filter(|&(n, _)| (1 << n) & filter.0 != 0)
.map(|(_, &e)| e)
.collect()
}
}
impl PlaneResourceHandles {
pub fn load_from_device<T>(device: &T) -> Result<Self>
where
T: Device,
{
let phandles = {
let mut raw: ffi::drm_mode_get_plane_res = Default::default();
unsafe {
try!(ffi::ioctl_mode_getplaneresources(
device.as_raw_fd(),
&mut raw
));
}
let phandles = PlaneResourceHandles {
planes: ffi_buf!(raw.plane_id_ptr, raw.count_planes),
};
unsafe {
try!(ffi::ioctl_mode_getplaneresources(
device.as_raw_fd(),
&mut raw
));
}
phandles
};
Ok(phandles)
}
pub fn planes<'a>(&'a self) -> &'a [plane::Handle] {
&self.planes
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum Type {
Connector,
Encoder,
Property,
Framebuffer,
Blob,
Plane,
Crtc,
Unknown,
}
#[warn(non_upper_case_globals)]
impl From<Type> for u32 {
fn from(n: Type) -> Self {
match n {
Type::Connector => ffi::DRM_MODE_OBJECT_CONNECTOR,
Type::Encoder => ffi::DRM_MODE_OBJECT_ENCODER,
Type::Property => ffi::DRM_MODE_OBJECT_PROPERTY,
Type::Framebuffer => ffi::DRM_MODE_OBJECT_FB,
Type::Blob => ffi::DRM_MODE_OBJECT_BLOB,
Type::Plane => ffi::DRM_MODE_OBJECT_PLANE,
Type::Crtc => ffi::DRM_MODE_OBJECT_CRTC,
Type::Unknown => ffi::DRM_MODE_OBJECT_ANY,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ResourceHandleType {
Connector(connector::Handle),
Encoder(encoder::Handle),
Crtc(crtc::Handle),
Framebuffer(framebuffer::Handle),
Plane(plane::Handle),
Property(property::Handle),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GammaLookupTable {
pub red: ffi::Buffer<u16>,
pub green: ffi::Buffer<u16>,
pub blue: ffi::Buffer<u16>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CrtcListFilter(u32);
#[derive(Debug, Clone, Copy)]
pub struct Mode {
mode: ffi::drm_mode_modeinfo,
}
impl Mode {
pub fn clock(&self) -> u32 {
self.mode.clock
}
pub fn size(&self) -> (u16, u16) {
(self.mode.hdisplay, self.mode.vdisplay)
}
pub fn hsync(&self) -> (u16, u16, u16) {
(self.mode.hsync_start, self.mode.hsync_end, self.mode.htotal)
}
pub fn vsync(&self) -> (u16, u16, u16) {
(self.mode.vsync_start, self.mode.vsync_end, self.mode.vtotal)
}
pub fn hskew(&self) -> u16 {
self.mode.hskew
}
pub fn vscan(&self) -> u16 {
self.mode.vscan
}
pub fn vrefresh(&self) -> u32 {
self.mode.vrefresh
}
pub fn name(&self) -> &CStr {
unsafe { CStr::from_ptr(&self.mode.name as *const _) }
}
}
impl PartialEq for Mode {
fn eq(&self, other: &Mode) -> bool {
self.mode.clock == other.mode.clock
&& self.mode.hdisplay == other.mode.hdisplay
&& self.mode.hsync_start == other.mode.hsync_start
&& self.mode.hsync_end == other.mode.hsync_end
&& self.mode.htotal == other.mode.htotal && self.mode.hskew == other.mode.hskew
&& self.mode.vdisplay == other.mode.vdisplay
&& self.mode.vsync_start == other.mode.vsync_start
&& self.mode.vsync_end == other.mode.vsync_end
&& self.mode.vtotal == other.mode.vtotal && self.mode.vscan == other.mode.vscan
&& self.mode.vrefresh == other.mode.vrefresh
&& self.mode.flags == other.mode.flags && self.mode.type_ == other.mode.type_
}
}
impl Eq for Mode {}
impl Hash for Mode {
fn hash<H>(&self, state: &mut H)
where H: Hasher
{
self.mode.clock.hash(state);
self.mode.hdisplay.hash(state);
self.mode.hsync_start.hash(state);
self.mode.hsync_end.hash(state);
self.mode.htotal.hash(state);
self.mode.vdisplay.hash(state);
self.mode.vsync_start.hash(state);
self.mode.vsync_end.hash(state);
self.mode.vtotal.hash(state);
self.mode.vrefresh.hash(state);
self.mode.flags.hash(state);
}
}
impl ::std::fmt::Debug for RawName {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
let cstr = unsafe { CStr::from_ptr(::std::mem::transmute(&self)) };
write!(f, "{:?}", cstr)
}
}