smithay/examples/raw_drm.rs

158 lines
5.0 KiB
Rust
Raw Normal View History

2018-12-15 20:58:43 +00:00
#![warn(rust_2018_idioms)]
2018-12-05 21:44:30 +00:00
#[macro_use]
extern crate slog;
use slog::Drain;
use smithay::{
backend::drm::{
2018-12-13 17:48:54 +00:00
device_bind,
2018-12-05 21:44:30 +00:00
legacy::{error::Error, LegacyDrmDevice, LegacyDrmSurface},
2018-12-13 17:48:54 +00:00
Device, DeviceHandler, RawSurface, Surface,
},
reexports::{
2019-02-05 16:26:09 +00:00
calloop::EventLoop,
2018-12-15 20:20:08 +00:00
drm::{
2020-04-07 13:15:29 +00:00
buffer::format::PixelFormat,
2018-12-15 20:20:08 +00:00
control::{
connector::{self, State as ConnectorState},
crtc,
dumbbuffer::DumbBuffer,
2020-04-07 13:15:29 +00:00
encoder, framebuffer, Device as ControlDevice,
2018-12-15 20:20:08 +00:00
},
2018-12-13 17:48:54 +00:00
},
2018-12-05 21:44:30 +00:00
},
};
use std::{
fs::{File, OpenOptions},
io::Error as IoError,
rc::Rc,
sync::Mutex,
};
fn main() {
let log = slog::Logger::root(Mutex::new(slog_term::term_full().fuse()).fuse(), o!());
/*
* Initialize the drm backend
*/
// "Find" a suitable drm device
let mut options = OpenOptions::new();
options.read(true);
options.write(true);
let mut device = LegacyDrmDevice::new(options.open("/dev/dri/card0").unwrap(), log.clone()).unwrap();
// Get a set of all modesetting resource handles (excluding planes):
let res_handles = Device::resource_handles(&device).unwrap();
// Use first connected connector
let connector_info = res_handles
.connectors()
.iter()
2020-04-07 13:15:29 +00:00
.map(|conn| device.get_connector_info(*conn).unwrap())
.find(|conn| conn.state() == ConnectorState::Connected)
2018-12-05 21:44:30 +00:00
.unwrap();
// Use the first encoder
2020-04-07 13:15:29 +00:00
let encoder = connector_info.encoders().iter().filter_map(|&e| e).next().unwrap();
let encoder_info = device.get_encoder_info(encoder).unwrap();
2018-12-05 21:44:30 +00:00
// use the connected crtc if any
let crtc = encoder_info
2020-04-07 13:15:29 +00:00
.crtc()
2018-12-05 21:44:30 +00:00
// or use the first one that is compatible with the encoder
.unwrap_or_else(|| {
*res_handles
.filter_crtcs(encoder_info.possible_crtcs())
.iter()
.next()
.unwrap()
});
// Assuming we found a good connector and loaded the info into `connector_info`
let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.)
// Initialize the hardware backend
let surface = Rc::new(device.create_surface(crtc).unwrap());
surface.use_mode(Some(mode)).unwrap();
for conn in surface.current_connectors().into_iter() {
if conn != connector_info.handle() {
surface.remove_connector(conn).unwrap();
}
}
surface.add_connector(connector_info.handle()).unwrap();
/*
* Lets create buffers and framebuffers.
* We use drm-rs DumbBuffers, because they always work and require little to no setup.
* But they are very slow, this is just for demonstration purposes.
*/
let (w, h) = mode.size();
2020-04-07 13:15:29 +00:00
let front_buffer = device.create_dumb_buffer((w as u32, h as u32), PixelFormat::XRGB8888).unwrap();
let front_framebuffer = device.add_framebuffer(&front_buffer).unwrap();
let back_buffer = device.create_dumb_buffer((w as u32, h as u32), PixelFormat::XRGB8888).unwrap();
let back_framebuffer = device.add_framebuffer(&back_buffer).unwrap();
2018-12-05 21:44:30 +00:00
device.set_handler(DrmHandlerImpl {
2020-04-07 13:15:29 +00:00
current: front_framebuffer,
front: (front_buffer, front_framebuffer),
2018-12-05 21:44:30 +00:00
back: (back_buffer, back_framebuffer),
surface: surface.clone(),
});
/*
* Register the DrmDevice on the EventLoop
*/
let mut event_loop = EventLoop::<()>::new().unwrap();
let _source = device_bind(&event_loop.handle(), device)
.map_err(|err| -> IoError { err.into() })
.unwrap();
// Start rendering
if surface.commit_pending() {
2020-04-07 13:15:29 +00:00
surface.commit(front_framebuffer).unwrap();
2018-12-05 21:44:30 +00:00
}
2020-04-07 13:15:29 +00:00
RawSurface::page_flip(&*surface, front_framebuffer).unwrap();
2018-12-05 21:44:30 +00:00
// Run
event_loop.run(None, &mut (), |_| {}).unwrap();
}
pub struct DrmHandlerImpl {
2020-04-07 13:15:29 +00:00
front: (DumbBuffer, framebuffer::Handle),
back: (DumbBuffer, framebuffer::Handle),
2018-12-05 21:44:30 +00:00
current: framebuffer::Handle,
surface: Rc<LegacyDrmSurface<File>>,
}
impl DeviceHandler for DrmHandlerImpl {
type Device = LegacyDrmDevice<File>;
fn vblank(&mut self, _crtc: crtc::Handle) {
{
// Swap and map buffer
2020-04-07 13:15:29 +00:00
let mut mapping = if self.current == self.front.1 {
self.current = self.back.1;
self.surface.map_dumb_buffer(&mut self.back.0).unwrap()
2018-12-05 21:44:30 +00:00
} else {
2020-04-07 13:15:29 +00:00
self.current = self.front.1;
self.surface.map_dumb_buffer(&mut self.front.0).unwrap()
2018-12-05 21:44:30 +00:00
};
// now we could render to the mapping via software rendering.
// this example just sets some grey color
2018-12-15 20:58:43 +00:00
for x in mapping.as_mut() {
2018-12-05 21:44:30 +00:00
*x = 128;
}
}
2020-04-07 13:15:29 +00:00
RawSurface::page_flip(&*self.surface, self.current).unwrap();
2018-12-05 21:44:30 +00:00
}
fn error(&mut self, error: Error) {
panic!("{:?}", error);
}
}