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-04-28 22:32:47 +00:00
allocator ::{ dumb ::DumbBuffer , Format , Fourcc , Modifier , Slot , Swapchain } ,
drm ::{ device_bind , DeviceHandler , DrmDevice , DrmError , 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 } ,
io ::Error as IoError ,
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-04-28 22:32:47 +00:00
let mut 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.)
2021-04-28 20:09:21 +00:00
// We just use one plane, the primary one
let plane = device . planes ( & crtc ) . unwrap ( ) . primary ;
2018-12-05 21:44:30 +00:00
// Initialize the hardware backend
2020-04-30 17:03:02 +00:00
let surface = Rc ::new (
device
2021-04-28 20:09:21 +00:00
. create_surface ( crtc , plane , 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-04-28 22:32:47 +00:00
let mut swapchain = Swapchain ::new (
allocator ,
w . into ( ) ,
h . into ( ) ,
Format {
code : Fourcc ::Argb8888 ,
modifier : Modifier ::Invalid ,
} ,
) ;
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-04-28 20:09:21 +00:00
first_buffer . set_userdata ( 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
2018-12-05 21:44:30 +00:00
device . set_handler ( DrmHandlerImpl {
2021-04-28 20:09:21 +00:00
swapchain ,
current : first_buffer ,
2018-12-05 21:44:30 +00:00
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
2021-04-28 20:09:21 +00:00
surface . commit ( framebuffer , true ) . unwrap ( ) ;
2018-12-05 21:44:30 +00:00
// Run
event_loop . run ( None , & mut ( ) , | _ | { } ) . unwrap ( ) ;
}
pub struct DrmHandlerImpl {
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
}
impl DeviceHandler for DrmHandlerImpl {
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-04-28 20:09:21 +00:00
next . set_userdata ( fb ) ;
}
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 ( ) ;
self . surface . page_flip ( fb , true ) . unwrap ( ) ;
2018-12-05 21:44:30 +00:00
}
2021-04-28 20:09:21 +00:00
fn error ( & mut self , error : DrmError ) {
2018-12-05 21:44:30 +00:00
panic! ( " {:?} " , error ) ;
}
}