diff --git a/Cargo.toml b/Cargo.toml index 1b8654b..86611c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ drm = { version = "^0.4.0-alpha1", git = "https://github.com/drakulix/drm-rs", b drm-ffi = { version = "^0.4.0-alpha1", git = "https://github.com/drakulix/drm-rs", branch = "next", optional = true } gbm = { version = "^0.6.0", git = "https://github.com/drakulix/gbm.rs", branch = "develop", optional = true, default-features = false, features = ["drm-support"] } input = { version = "0.5", default-features = false, optional = true } +image = { version = "0.23.14", default-features = false, optional = true } lazy_static = "1" libc = "0.2.70" libloading = "0.7.0" @@ -62,9 +63,5 @@ xwayland = ["wayland_frontend"] test_all_features = ["default"] [[example]] -name = "raw_legacy_drm" -required-features = ["backend_drm"] - -[[example]] -name = "raw_atomic_drm" +name = "raw_drm" required-features = ["backend_drm"] diff --git a/examples/raw_atomic_drm.rs b/examples/raw_atomic_drm.rs deleted file mode 100644 index d0a0424..0000000 --- a/examples/raw_atomic_drm.rs +++ /dev/null @@ -1,182 +0,0 @@ -#![warn(rust_2018_idioms)] - -#[macro_use] -extern crate slog; - -use slog::Drain; -use smithay::{ - backend::drm::{ - atomic::{AtomicDrmDevice, AtomicDrmSurface}, - common::Error, - device_bind, Device, DeviceHandler, RawSurface, Surface, - }, - reexports::{ - calloop::EventLoop, - drm::{ - buffer::format::PixelFormat, - control::{ - connector::State as ConnectorState, crtc, dumbbuffer::DumbBuffer, framebuffer, property, - Device as ControlDevice, ResourceHandle, - }, - }, - }, -}; -use std::{ - fs::{File, OpenOptions}, - io::Error as IoError, - rc::Rc, - sync::Mutex, -}; - -fn get_property_by_name( - dev: &D, - handle: T, - name: &'static str, -) -> Option<(property::ValueType, property::RawValue)> { - let props = dev.get_properties(handle).expect("Could not get props"); - let (ids, vals) = props.as_props_and_values(); - for (&id, &val) in ids.iter().zip(vals.iter()) { - let info = dev.get_property(id).unwrap(); - if info.name().to_str().map(|x| x == name).unwrap_or(false) { - let val_ty = info.value_type(); - return Some((val_ty, val)); - } - } - None -} - -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 = - AtomicDrmDevice::new(options.open("/dev/dri/card0").unwrap(), true, 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() - .map(|conn| device.get_connector_info(*conn).unwrap()) - .find(|conn| conn.state() == ConnectorState::Connected) - .unwrap(); - - // use the connected crtc if any - let (val_ty, raw) = get_property_by_name(&device, connector_info.handle(), "CRTC_ID").unwrap(); - let crtc = match val_ty.convert_value(raw) { - property::Value::CRTC(Some(handle)) => handle, - property::Value::CRTC(None) => { - // Use the first encoder - let encoder = connector_info - .encoders() - .iter() - .filter_map(|&e| e) - .next() - .unwrap(); - let encoder_info = device.get_encoder_info(encoder).unwrap(); - - res_handles.filter_crtcs(encoder_info.possible_crtcs())[0] - } - _ => unreachable!("CRTC_ID does not return another property type"), - }; - - // 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, mode, &[connector_info.handle()]) - .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(); - 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(); - - device.set_handler(DrmHandlerImpl { - current: front_framebuffer, - front: (front_buffer, front_framebuffer), - 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() { - surface.commit(front_framebuffer).unwrap(); - } - - // Run - event_loop.run(None, &mut (), |_| {}).unwrap(); -} - -pub struct DrmHandlerImpl { - front: (DumbBuffer, framebuffer::Handle), - back: (DumbBuffer, framebuffer::Handle), - current: framebuffer::Handle, - surface: Rc>, -} - -impl DeviceHandler for DrmHandlerImpl { - type Device = AtomicDrmDevice; - - fn vblank(&mut self, _crtc: crtc::Handle) { - { - // Swap and map buffer - let mut mapping = if self.current == self.front.1 { - self.current = self.back.1; - self.surface.map_dumb_buffer(&mut self.back.0).unwrap() - } else { - self.current = self.front.1; - self.surface.map_dumb_buffer(&mut self.front.0).unwrap() - }; - - // now we could render to the mapping via software rendering. - // this example just sets some grey color - - for x in mapping.as_mut() { - *x = 128; - } - } - RawSurface::page_flip(&*self.surface, self.current).unwrap(); - } - - fn error(&mut self, error: Error) { - panic!("{:?}", error); - } -} diff --git a/examples/raw_legacy_drm.rs b/examples/raw_drm.rs similarity index 54% rename from examples/raw_legacy_drm.rs rename to examples/raw_drm.rs index 0f6a874..2e72b87 100644 --- a/examples/raw_legacy_drm.rs +++ b/examples/raw_drm.rs @@ -5,18 +5,20 @@ extern crate slog; use slog::Drain; use smithay::{ - backend::drm::{ - common::Error, - device_bind, - legacy::{LegacyDrmDevice, LegacyDrmSurface}, - Device, DeviceHandler, RawSurface, + backend::{ + allocator::{Format, Fourcc, Modifier, Swapchain, Slot, dumb::DumbBuffer}, + drm::{ + DrmError, + DrmDevice, DrmSurface, + DeviceHandler, + device_bind, + } }, reexports::{ calloop::EventLoop, drm::{ - buffer::format::PixelFormat, control::{ - connector::State as ConnectorState, crtc, dumbbuffer::DumbBuffer, framebuffer, + connector::State as ConnectorState, crtc, framebuffer, Device as ControlDevice, }, }, @@ -24,11 +26,23 @@ use smithay::{ }; use std::{ fs::{File, OpenOptions}, + os::unix::io::{AsRawFd, RawFd}, io::Error as IoError, rc::Rc, sync::Mutex, }; +#[derive(Clone)] +struct FdWrapper { + file: Rc, +} + +impl AsRawFd for FdWrapper { + fn as_raw_fd(&self) -> RawFd { + self.file.as_raw_fd() + } +} + fn main() { let log = slog::Logger::root(Mutex::new(slog_term::term_full().fuse()).fuse(), o!()); @@ -40,17 +54,19 @@ fn main() { let mut options = OpenOptions::new(); options.read(true); options.write(true); + let fd = FdWrapper { file: Rc::new(options.open("/dev/dri/card0").unwrap()) }; + let mut device = - LegacyDrmDevice::new(options.open("/dev/dri/card0").unwrap(), true, log.clone()).unwrap(); + DrmDevice::new(fd.clone(), true, log.clone()).unwrap(); // Get a set of all modesetting resource handles (excluding planes): - let res_handles = Device::resource_handles(&device).unwrap(); + let res_handles = ControlDevice::resource_handles(&device).unwrap(); // Use first connected connector let connector_info = res_handles .connectors() .iter() - .map(|conn| device.get_connector_info(*conn).unwrap()) + .map(|conn| device.get_connector(*conn).unwrap()) .find(|conn| conn.state() == ConnectorState::Connected) .unwrap(); @@ -61,7 +77,7 @@ fn main() { .filter_map(|&e| e) .next() .unwrap(); - let encoder_info = device.get_encoder_info(encoder).unwrap(); + let encoder_info = device.get_encoder(encoder).unwrap(); // use the connected crtc if any let crtc = encoder_info @@ -72,10 +88,13 @@ fn main() { // 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.) + // We just use one plane, the primary one + let plane = device.planes(&crtc).unwrap().primary; + // Initialize the hardware backend let surface = Rc::new( device - .create_surface(crtc, mode, &[connector_info.handle()]) + .create_surface(crtc, plane, mode, &[connector_info.handle()]) .unwrap(), ); @@ -85,19 +104,16 @@ fn main() { * But they are very slow, this is just for demonstration purposes. */ let (w, h) = mode.size(); - 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(); + let allocator = DrmDevice::new(fd, false, log.clone()).unwrap(); + let mut swapchain = Swapchain::new(allocator, w.into(), h.into(), Format { code: Fourcc::Argb8888, modifier: Modifier::Invalid }); + let first_buffer: Slot, _> = swapchain.acquire().unwrap().unwrap(); + let framebuffer = surface.add_framebuffer(&first_buffer.handle, 32, 32).unwrap(); + first_buffer.set_userdata(framebuffer); + // Get the device as an allocator into the device.set_handler(DrmHandlerImpl { - current: front_framebuffer, - front: (front_buffer, front_framebuffer), - back: (back_buffer, back_framebuffer), + swapchain, + current: first_buffer, surface: surface.clone(), }); @@ -110,46 +126,44 @@ fn main() { .unwrap(); // Start rendering - if surface.commit_pending() { - surface.commit(front_framebuffer).unwrap(); - } + surface.commit(framebuffer, true).unwrap(); // Run event_loop.run(None, &mut (), |_| {}).unwrap(); } pub struct DrmHandlerImpl { - front: (DumbBuffer, framebuffer::Handle), - back: (DumbBuffer, framebuffer::Handle), - current: framebuffer::Handle, - surface: Rc>, + swapchain: Swapchain, DumbBuffer, framebuffer::Handle, DumbBuffer>, + current: Slot, framebuffer::Handle>, + surface: Rc>, } impl DeviceHandler for DrmHandlerImpl { - type Device = LegacyDrmDevice; - fn vblank(&mut self, _crtc: crtc::Handle) { { - // Swap and map buffer - let mut mapping = if self.current == self.front.1 { - self.current = self.back.1; - self.surface.map_dumb_buffer(&mut self.back.0).unwrap() - } else { - self.current = self.front.1; - self.surface.map_dumb_buffer(&mut self.front.0).unwrap() - }; + // Next buffer + let next = self.swapchain.acquire().unwrap().unwrap(); + if next.userdata().is_none() { + let fb = self.surface.add_framebuffer(&next.handle, 32, 32).unwrap(); + next.set_userdata(fb); + } // now we could render to the mapping via software rendering. // this example just sets some grey color + let mut db = next.handle; + let mut mapping = self.surface.map_dumb_buffer(&mut db).unwrap(); for x in mapping.as_mut() { *x = 128; } + self.current = next; } - RawSurface::page_flip(&*self.surface, self.current).unwrap(); + + let fb = self.current.userdata().unwrap(); + self.surface.page_flip(fb, true).unwrap(); } - fn error(&mut self, error: Error) { + fn error(&mut self, error: DrmError) { panic!("{:?}", error); } }