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 ::{
2021-04-28 20:09:21 +00:00
backend ::{
2021-05-29 19:09:38 +00:00
allocator ::{ dumb ::DumbBuffer , Fourcc , Slot , Swapchain } ,
2021-05-30 20:01:36 +00:00
drm ::{ DrmDevice , DrmEvent , DrmSurface } ,
2018-12-13 17:48:54 +00:00
} ,
reexports ::{
2019-02-05 16:26:09 +00:00
calloop ::EventLoop ,
2021-04-28 22:32:47 +00:00
drm ::control ::{ connector ::State as ConnectorState , crtc , framebuffer , Device as ControlDevice } ,
2018-12-05 21:44:30 +00:00
} ,
} ;
use std ::{
fs ::{ File , OpenOptions } ,
2021-04-28 22:32:47 +00:00
os ::unix ::io ::{ AsRawFd , RawFd } ,
2018-12-05 21:44:30 +00:00
rc ::Rc ,
sync ::Mutex ,
} ;
2021-04-28 20:09:21 +00:00
#[ derive(Clone) ]
struct FdWrapper {
file : Rc < File > ,
}
impl AsRawFd for FdWrapper {
fn as_raw_fd ( & self ) -> RawFd {
self . file . as_raw_fd ( )
}
}
2018-12-05 21:44:30 +00:00
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 ) ;
2021-04-28 22:32:47 +00:00
let fd = FdWrapper {
file : Rc ::new ( options . open ( " /dev/dri/card0 " ) . unwrap ( ) ) ,
} ;
2021-04-28 20:09:21 +00:00
2021-05-30 20:01:36 +00:00
let device = DrmDevice ::new ( fd . clone ( ) , true , log . clone ( ) ) . unwrap ( ) ;
2018-12-05 21:44:30 +00:00
// Get a set of all modesetting resource handles (excluding planes):
2021-04-28 20:09:21 +00:00
let res_handles = ControlDevice ::resource_handles ( & device ) . unwrap ( ) ;
2018-12-05 21:44:30 +00:00
// Use first connected connector
let connector_info = res_handles
. connectors ( )
. iter ( )
2021-04-28 20:09:21 +00:00
. map ( | conn | device . get_connector ( * conn ) . unwrap ( ) )
2020-04-07 13:15:29 +00:00
. find ( | conn | conn . state ( ) = = ConnectorState ::Connected )
2018-12-05 21:44:30 +00:00
. unwrap ( ) ;
// Use the first encoder
2020-04-10 15:01:49 +00:00
let encoder = connector_info
. encoders ( )
. iter ( )
. filter_map ( | & e | e )
. next ( )
. unwrap ( ) ;
2021-04-28 20:09:21 +00:00
let encoder_info = device . get_encoder ( 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
2020-09-14 22:49:10 +00:00
. unwrap_or_else ( | | res_handles . filter_crtcs ( encoder_info . possible_crtcs ( ) ) [ 0 ] ) ;
2018-12-05 21:44:30 +00:00
// 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
2020-04-30 17:03:02 +00:00
let surface = Rc ::new (
device
2021-05-19 23:06:16 +00:00
. create_surface ( crtc , mode , & [ connector_info . handle ( ) ] )
2020-04-30 17:03:02 +00:00
. unwrap ( ) ,
) ;
2018-12-05 21:44:30 +00:00
/*
* 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 ( ) ;
2021-04-28 20:09:21 +00:00
let allocator = DrmDevice ::new ( fd , false , log . clone ( ) ) . unwrap ( ) ;
2021-05-29 19:09:38 +00:00
let mods = surface
. supported_formats ( surface . plane ( ) )
. expect ( " Unable to readout formats for surface " )
. iter ( )
2021-06-09 20:12:35 +00:00
. filter_map ( | format | {
if format . code = = Fourcc ::Argb8888 {
Some ( format . modifier )
} else {
None
}
} )
2021-05-29 19:09:38 +00:00
. collect ::< Vec < _ > > ( ) ;
2021-06-09 20:12:35 +00:00
let mut swapchain = Swapchain ::new ( allocator , w . into ( ) , h . into ( ) , Fourcc ::Argb8888 , mods ) ;
2021-04-28 20:09:21 +00:00
let first_buffer : Slot < DumbBuffer < FdWrapper > , _ > = swapchain . acquire ( ) . unwrap ( ) . unwrap ( ) ;
2021-04-30 15:21:35 +00:00
let framebuffer = surface . add_framebuffer ( first_buffer . handle ( ) , 32 , 32 ) . unwrap ( ) ;
2021-05-23 13:13:04 +00:00
* first_buffer . userdata ( ) = Some ( framebuffer ) ;
2018-12-05 21:44:30 +00:00
2021-04-28 22:32:47 +00:00
// Get the device as an allocator into the
2021-05-30 20:01:36 +00:00
let mut vblank_handler = VBlankHandler {
2021-04-28 20:09:21 +00:00
swapchain ,
current : first_buffer ,
2018-12-05 21:44:30 +00:00
surface : surface . clone ( ) ,
2021-05-30 20:01:36 +00:00
} ;
2018-12-05 21:44:30 +00:00
/*
* Register the DrmDevice on the EventLoop
* /
2021-05-30 20:01:36 +00:00
let mut event_loop = EventLoop ::< ( ) > ::try_new ( ) . unwrap ( ) ;
event_loop
. handle ( )
. insert_source ( device , move | event , _ : & mut ( ) , _ : & mut ( ) | match event {
DrmEvent ::VBlank ( crtc ) = > vblank_handler . vblank ( crtc ) ,
DrmEvent ::Error ( e ) = > panic! ( " {} " , e ) ,
} )
2018-12-05 21:44:30 +00:00
. unwrap ( ) ;
// Start rendering
2021-05-26 17:12:45 +00:00
surface
. commit ( [ ( framebuffer , surface . plane ( ) ) ] . iter ( ) , true )
. unwrap ( ) ;
2018-12-05 21:44:30 +00:00
// Run
event_loop . run ( None , & mut ( ) , | _ | { } ) . unwrap ( ) ;
}
2021-05-30 20:01:36 +00:00
pub struct VBlankHandler {
2021-05-15 16:17:43 +00:00
swapchain : Swapchain < DrmDevice < FdWrapper > , DumbBuffer < FdWrapper > , framebuffer ::Handle > ,
2021-04-28 20:09:21 +00:00
current : Slot < DumbBuffer < FdWrapper > , framebuffer ::Handle > ,
surface : Rc < DrmSurface < FdWrapper > > ,
2018-12-05 21:44:30 +00:00
}
2021-05-30 20:01:36 +00:00
impl VBlankHandler {
2018-12-05 21:44:30 +00:00
fn vblank ( & mut self , _crtc : crtc ::Handle ) {
{
2021-04-28 20:09:21 +00:00
// Next buffer
let next = self . swapchain . acquire ( ) . unwrap ( ) . unwrap ( ) ;
if next . userdata ( ) . is_none ( ) {
2021-04-30 15:21:35 +00:00
let fb = self . surface . add_framebuffer ( next . handle ( ) , 32 , 32 ) . unwrap ( ) ;
2021-05-23 13:13:04 +00:00
* next . userdata ( ) = Some ( fb ) ;
2021-04-28 20:09:21 +00:00
}
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
2021-04-30 15:21:35 +00:00
{
let mut db = * next . handle ( ) ;
let mut mapping = self . surface . map_dumb_buffer ( & mut db ) . unwrap ( ) ;
for x in mapping . as_mut ( ) {
* x = 128 ;
}
2018-12-05 21:44:30 +00:00
}
2021-04-28 20:09:21 +00:00
self . current = next ;
2018-12-05 21:44:30 +00:00
}
2021-04-28 20:09:21 +00:00
let fb = self . current . userdata ( ) . unwrap ( ) ;
2021-05-26 17:12:45 +00:00
self . surface
. page_flip ( [ ( fb , self . surface . plane ( ) ) ] . iter ( ) , true )
. unwrap ( ) ;
2018-12-05 21:44:30 +00:00
}
}