use result::*;
use ffi;
use std::ffi::CStr;
use std::hash::Hash;
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)]
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 {
framebuffer::create(self, buffer)
}
}
pub trait ResourceHandle: Eq + Copy + Hash {
fn from_raw(RawHandle) -> Self;
fn as_raw(&self) -> 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 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.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_ &&
self.mode.name == other.mode.name
}
}
impl Eq for Mode {}
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)
}
}