Merge pull request #143 from Smithay/drm-next

drm-rs 0.4
This commit is contained in:
Victor Brekenfeld 2020-04-10 16:59:32 +02:00 committed by GitHub
commit cceb9dabf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 182 additions and 136 deletions

View File

@ -16,7 +16,7 @@ wayland-commons = { version = "0.25.0", optional = true }
wayland-sys = { version = "0.25.0", optional = true } wayland-sys = { version = "0.25.0", optional = true }
calloop = "0.5.1" calloop = "0.5.1"
bitflags = "1" bitflags = "1"
nix = "0.13" nix = "0.15"
xkbcommon = "0.4.0" xkbcommon = "0.4.0"
tempfile = "3.0" tempfile = "3.0"
slog = "2.1.1" slog = "2.1.1"
@ -24,8 +24,8 @@ slog-stdlog = "3.0.2"
libloading = "0.5.0" libloading = "0.5.0"
wayland-client = { version = "0.23.4", features = ["egl"], optional = true } wayland-client = { version = "0.23.4", features = ["egl"], optional = true }
winit = { version = "0.22.0", optional = true } winit = { version = "0.22.0", optional = true }
drm = { version = "^0.3.4", optional = true } drm = { version = "^0.4.0", git = "https://github.com/drakulix/drm-rs", branch = "develop", optional = true }
gbm = { version = "^0.5.0", optional = true, default-features = false, features = ["drm-support"] } gbm = { version = "^0.6.0", git = "https://github.com/drakulix/gbm.rs", branch = "develop", optional = true, default-features = false, features = ["drm-support"] }
glium = { version = "0.23.0", optional = true, default-features = false } glium = { version = "0.23.0", optional = true, default-features = false }
input = { version = "0.4.1", optional = true } input = { version = "0.4.1", optional = true }
udev = { version = "0.2.0", optional = true } udev = { version = "0.2.0", optional = true }
@ -35,6 +35,7 @@ wayland-protocols = { version = "0.25.0", features = ["unstable_protocols", "ser
image = { version = "0.21.0", optional = true } image = { version = "0.21.0", optional = true }
error-chain = "0.12.0" error-chain = "0.12.0"
lazy_static = "1.0.0" lazy_static = "1.0.0"
failure = { version = "0.1.5", optional = true }
[dev-dependencies] [dev-dependencies]
slog-term = "2.3" slog-term = "2.3"
@ -45,7 +46,7 @@ gl_generator = { version = "0.10", optional = true }
[features] [features]
default = ["backend_winit", "backend_drm_legacy", "backend_drm_gbm", "backend_drm_egl", "backend_libinput", "backend_udev", "backend_session_logind", "renderer_glium", "xwayland", "wayland_frontend"] default = ["backend_winit", "backend_drm_legacy", "backend_drm_gbm", "backend_drm_egl", "backend_libinput", "backend_udev", "backend_session_logind", "renderer_glium", "xwayland", "wayland_frontend"]
backend_winit = ["winit", "wayland-server/dlopen", "wayland-client/dlopen", "backend_egl", "renderer_gl", "use_system_lib"] backend_winit = ["winit", "wayland-server/dlopen", "wayland-client/dlopen", "backend_egl", "renderer_gl", "use_system_lib"]
backend_drm = ["drm"] backend_drm = ["drm", "failure"]
backend_drm_legacy = ["backend_drm"] backend_drm_legacy = ["backend_drm"]
backend_drm_gbm = ["backend_drm", "gbm", "image"] backend_drm_gbm = ["backend_drm", "gbm", "image"]
backend_drm_egl = ["backend_drm", "backend_egl"] backend_drm_egl = ["backend_drm", "backend_egl"]

View File

@ -323,9 +323,9 @@ impl<S: SessionNotifier, Data: 'static> UdevHandlerImpl<S, Data> {
let connector_infos: Vec<ConnectorInfo> = res_handles let connector_infos: Vec<ConnectorInfo> = res_handles
.connectors() .connectors()
.iter() .iter()
.map(|conn| device.resource_info::<ConnectorInfo>(*conn).unwrap()) .map(|conn| device.get_connector_info(*conn).unwrap())
.filter(|conn| conn.connection_state() == ConnectorState::Connected) .filter(|conn| conn.state() == ConnectorState::Connected)
.inspect(|conn| info!(logger, "Connected: {:?}", conn.connector_type())) .inspect(|conn| info!(logger, "Connected: {:?}", conn.interface()))
.collect(); .collect();
let mut backends = HashMap::new(); let mut backends = HashMap::new();
@ -335,7 +335,8 @@ impl<S: SessionNotifier, Data: 'static> UdevHandlerImpl<S, Data> {
let encoder_infos = connector_info let encoder_infos = connector_info
.encoders() .encoders()
.iter() .iter()
.flat_map(|encoder_handle| device.resource_info::<EncoderInfo>(*encoder_handle)) .filter_map(|e| *e)
.flat_map(|encoder_handle| device.get_encoder_info(encoder_handle))
.collect::<Vec<EncoderInfo>>(); .collect::<Vec<EncoderInfo>>();
for encoder_info in encoder_infos { for encoder_info in encoder_infos {
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) { for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {

View File

@ -13,12 +13,12 @@ use smithay::{
reexports::{ reexports::{
calloop::EventLoop, calloop::EventLoop,
drm::{ drm::{
buffer::PixelFormat, buffer::format::PixelFormat,
control::{ control::{
connector::{self, State as ConnectorState}, connector::{self, State as ConnectorState},
crtc, crtc,
dumbbuffer::DumbBuffer, dumbbuffer::DumbBuffer,
encoder, framebuffer, Device as ControlDevice, ResourceInfo, encoder, framebuffer, Device as ControlDevice,
}, },
}, },
}, },
@ -50,16 +50,17 @@ fn main() {
let connector_info = res_handles let connector_info = res_handles
.connectors() .connectors()
.iter() .iter()
.map(|conn| Device::resource_info::<connector::Info>(&device, *conn).unwrap()) .map(|conn| device.get_connector_info(*conn).unwrap())
.find(|conn| conn.connection_state() == ConnectorState::Connected) .find(|conn| conn.state() == ConnectorState::Connected)
.unwrap(); .unwrap();
// Use the first encoder // Use the first encoder
let encoder_info = Device::resource_info::<encoder::Info>(&device, connector_info.encoders()[0]).unwrap(); let encoder = connector_info.encoders().iter().filter_map(|&e| e).next().unwrap();
let encoder_info = device.get_encoder_info(encoder).unwrap();
// use the connected crtc if any // use the connected crtc if any
let crtc = encoder_info let crtc = encoder_info
.current_crtc() .crtc()
// or use the first one that is compatible with the encoder // or use the first one that is compatible with the encoder
.unwrap_or_else(|| { .unwrap_or_else(|| {
*res_handles *res_handles
@ -89,16 +90,14 @@ fn main() {
* But they are very slow, this is just for demonstration purposes. * But they are very slow, this is just for demonstration purposes.
*/ */
let (w, h) = mode.size(); let (w, h) = mode.size();
let front_buffer = let front_buffer = device.create_dumb_buffer((w as u32, h as u32), PixelFormat::XRGB8888).unwrap();
DumbBuffer::create_from_device(&device, (w as u32, h as u32), PixelFormat::XRGB8888).unwrap(); let front_framebuffer = device.add_framebuffer(&front_buffer).unwrap();
let front_framebuffer = device.create_framebuffer(&front_buffer).unwrap(); let back_buffer = device.create_dumb_buffer((w as u32, h as u32), PixelFormat::XRGB8888).unwrap();
let back_buffer = let back_framebuffer = device.add_framebuffer(&back_buffer).unwrap();
DumbBuffer::create_from_device(&device, (w as u32, h as u32), PixelFormat::XRGB8888).unwrap();
let back_framebuffer = device.create_framebuffer(&back_buffer).unwrap();
device.set_handler(DrmHandlerImpl { device.set_handler(DrmHandlerImpl {
current: front_framebuffer.handle(), current: front_framebuffer,
front: (front_buffer, front_framebuffer.clone()), front: (front_buffer, front_framebuffer),
back: (back_buffer, back_framebuffer), back: (back_buffer, back_framebuffer),
surface: surface.clone(), surface: surface.clone(),
}); });
@ -113,17 +112,17 @@ fn main() {
// Start rendering // Start rendering
if surface.commit_pending() { if surface.commit_pending() {
surface.commit(front_framebuffer.handle()).unwrap(); surface.commit(front_framebuffer).unwrap();
} }
surface.page_flip(front_framebuffer.handle()).unwrap(); RawSurface::page_flip(&*surface, front_framebuffer).unwrap();
// Run // Run
event_loop.run(None, &mut (), |_| {}).unwrap(); event_loop.run(None, &mut (), |_| {}).unwrap();
} }
pub struct DrmHandlerImpl { pub struct DrmHandlerImpl {
front: (DumbBuffer, framebuffer::Info), front: (DumbBuffer, framebuffer::Handle),
back: (DumbBuffer, framebuffer::Info), back: (DumbBuffer, framebuffer::Handle),
current: framebuffer::Handle, current: framebuffer::Handle,
surface: Rc<LegacyDrmSurface<File>>, surface: Rc<LegacyDrmSurface<File>>,
} }
@ -134,12 +133,12 @@ impl DeviceHandler for DrmHandlerImpl {
fn vblank(&mut self, _crtc: crtc::Handle) { fn vblank(&mut self, _crtc: crtc::Handle) {
{ {
// Swap and map buffer // Swap and map buffer
let mut mapping = if self.current == self.front.1.handle() { let mut mapping = if self.current == self.front.1 {
self.current = self.back.1.handle(); self.current = self.back.1;
self.back.0.map(&*self.surface).unwrap() self.surface.map_dumb_buffer(&mut self.back.0).unwrap()
} else { } else {
self.current = self.front.1.handle(); self.current = self.front.1;
self.front.0.map(&*self.surface).unwrap() self.surface.map_dumb_buffer(&mut self.front.0).unwrap()
}; };
// now we could render to the mapping via software rendering. // now we could render to the mapping via software rendering.
@ -149,7 +148,7 @@ impl DeviceHandler for DrmHandlerImpl {
*x = 128; *x = 128;
} }
} }
self.surface.page_flip(self.current).unwrap(); RawSurface::page_flip(&*self.surface, self.current).unwrap();
} }
fn error(&mut self, error: Error) { fn error(&mut self, error: Error) {

View File

@ -8,7 +8,8 @@
//! Take a look at `anvil`s source code for an example of this. //! Take a look at `anvil`s source code for an example of this.
//! //!
use drm::control::{crtc, ResourceHandles, ResourceInfo}; use drm::control::{crtc, connector, encoder, framebuffer, plane, ResourceHandles};
use drm::SystemError as DrmError;
use nix::libc::dev_t; use nix::libc::dev_t;
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
use std::rc::Rc; use std::rc::Rc;
@ -166,19 +167,28 @@ where
self.dev.borrow_mut().process_events() self.dev.borrow_mut().process_events()
} }
fn resource_info<T: ResourceInfo>(&self, handle: T::Handle) -> Result<T> {
self.dev
.borrow()
.resource_info(handle)
.chain_err(|| ErrorKind::UnderlyingBackendError)
}
fn resource_handles(&self) -> Result<ResourceHandles> { fn resource_handles(&self) -> Result<ResourceHandles> {
self.dev self.dev
.borrow() .borrow()
.resource_handles() .resource_handles()
.chain_err(|| ErrorKind::UnderlyingBackendError) .chain_err(|| ErrorKind::UnderlyingBackendError)
} }
fn get_connector_info(&self, conn: connector::Handle) -> std::result::Result<connector::Info, DrmError> {
self.dev.borrow().get_connector_info(conn)
}
fn get_crtc_info(&self, crtc: crtc::Handle) -> std::result::Result<crtc::Info, DrmError> {
self.dev.borrow().get_crtc_info(crtc)
}
fn get_encoder_info(&self, enc: encoder::Handle) -> std::result::Result<encoder::Info, DrmError> {
self.dev.borrow().get_encoder_info(enc)
}
fn get_framebuffer_info(&self, fb: framebuffer::Handle) -> std::result::Result<framebuffer::Info, DrmError> {
self.dev.borrow().get_framebuffer_info(fb)
}
fn get_plane_info(&self, plane: plane::Handle) -> std::result::Result<plane::Info, DrmError> {
self.dev.borrow().get_plane_info(plane)
}
} }
#[cfg(feature = "use_system_lib")] #[cfg(feature = "use_system_lib")]

View File

@ -9,9 +9,11 @@
//! of [`GbmSurface::page_flip`](::backend::drm::gbm::GbmSurface::page_flip). //! of [`GbmSurface::page_flip`](::backend::drm::gbm::GbmSurface::page_flip).
//! //!
use super::{Device, DeviceHandler, RawDevice, ResourceHandles, ResourceInfo, Surface}; use super::{Device, DeviceHandler, RawDevice, ResourceHandles, Surface};
use drm::control::{crtc, Device as ControlDevice}; use drm::control::{crtc, connector, encoder, framebuffer, plane, Device as ControlDevice};
use drm::SystemError as DrmError;
use failure::ResultExt as FailureResultExt;
use gbm::{self, BufferObjectFlags, Format as GbmFormat}; use gbm::{self, BufferObjectFlags, Format as GbmFormat};
use nix::libc::dev_t; use nix::libc::dev_t;
@ -185,19 +187,29 @@ impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D> {
self.dev.borrow_mut().process_events() self.dev.borrow_mut().process_events()
} }
fn resource_info<T: ResourceInfo>(&self, handle: T::Handle) -> Result<T> {
self.dev
.borrow()
.resource_info(handle)
.chain_err(|| ErrorKind::UnderlyingBackendError)
}
fn resource_handles(&self) -> Result<ResourceHandles> { fn resource_handles(&self) -> Result<ResourceHandles> {
self.dev self.dev
.borrow() .borrow()
.resource_handles() .resource_handles()
.compat()
.chain_err(|| ErrorKind::UnderlyingBackendError) .chain_err(|| ErrorKind::UnderlyingBackendError)
} }
fn get_connector_info(&self, conn: connector::Handle) -> std::result::Result<connector::Info, DrmError> {
self.dev.borrow().get_connector_info(conn)
}
fn get_crtc_info(&self, crtc: crtc::Handle) -> std::result::Result<crtc::Info, DrmError> {
self.dev.borrow().get_crtc_info(crtc)
}
fn get_encoder_info(&self, enc: encoder::Handle) -> std::result::Result<encoder::Info, DrmError> {
self.dev.borrow().get_encoder_info(enc)
}
fn get_framebuffer_info(&self, fb: framebuffer::Handle) -> std::result::Result<framebuffer::Info, DrmError> {
self.dev.borrow().get_framebuffer_info(fb)
}
fn get_plane_info(&self, plane: plane::Handle) -> std::result::Result<plane::Info, DrmError> {
self.dev.borrow().get_plane_info(plane)
}
} }
impl<D: RawDevice + ControlDevice + 'static> AsRawFd for GbmDevice<D> { impl<D: RawDevice + ControlDevice + 'static> AsRawFd for GbmDevice<D> {

View File

@ -3,7 +3,7 @@
//! to an open [`Session`](::backend::session::Session). //! to an open [`Session`](::backend::session::Session).
//! //!
use drm::control::{crtc, Device as ControlDevice, ResourceInfo}; use drm::control::crtc;
use gbm::BufferObject; use gbm::BufferObject;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
@ -19,14 +19,14 @@ use crate::backend::session::{AsSessionObserver, SessionObserver};
/// created from. /// created from.
pub struct GbmDeviceObserver< pub struct GbmDeviceObserver<
S: SessionObserver + 'static, S: SessionObserver + 'static,
D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static, D: RawDevice + ::drm::control::Device + AsSessionObserver<S> + 'static,
> { > {
observer: S, observer: S,
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<GbmSurfaceInternal<D>>>>>, backends: Weak<RefCell<HashMap<crtc::Handle, Weak<GbmSurfaceInternal<D>>>>>,
logger: ::slog::Logger, logger: ::slog::Logger,
} }
impl<S: SessionObserver + 'static, D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static> impl<S: SessionObserver + 'static, D: RawDevice + ::drm::control::Device + AsSessionObserver<S> + 'static>
AsSessionObserver<GbmDeviceObserver<S, D>> for GbmDevice<D> AsSessionObserver<GbmDeviceObserver<S, D>> for GbmDevice<D>
{ {
fn observer(&mut self) -> GbmDeviceObserver<S, D> { fn observer(&mut self) -> GbmDeviceObserver<S, D> {
@ -38,7 +38,7 @@ impl<S: SessionObserver + 'static, D: RawDevice + ControlDevice + AsSessionObser
} }
} }
impl<S: SessionObserver + 'static, D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static> impl<S: SessionObserver + 'static, D: RawDevice + ::drm::control::Device + AsSessionObserver<S> + 'static>
SessionObserver for GbmDeviceObserver<S, D> SessionObserver for GbmDeviceObserver<S, D>
{ {
fn pause(&mut self, devnum: Option<(u32, u32)>) { fn pause(&mut self, devnum: Option<(u32, u32)>) {
@ -55,23 +55,24 @@ impl<S: SessionObserver + 'static, D: RawDevice + ControlDevice + AsSessionObser
if let Some(Err(err)) = backend if let Some(Err(err)) = backend
.current_frame_buffer .current_frame_buffer
.get() .get()
.map(|fb| backend.crtc.page_flip(fb.handle())) .map(|fb| backend.crtc.page_flip(fb))
{ {
warn!(self.logger, "Failed to restart rendering loop. Error: {}", err); warn!(self.logger, "Failed to restart rendering loop. Error: {}", err);
} }
// reset cursor // reset cursor
{ {
use ::drm::control::Device;
let &(ref cursor, ref hotspot): &(BufferObject<()>, (u32, u32)) = let &(ref cursor, ref hotspot): &(BufferObject<()>, (u32, u32)) =
unsafe { &*backend.cursor.as_ptr() }; unsafe { &*backend.cursor.as_ptr() };
if crtc::set_cursor2( if backend.dev.borrow().set_cursor2(
&*backend.dev.borrow(),
*crtc, *crtc,
cursor, Some(cursor),
((*hotspot).0 as i32, (*hotspot).1 as i32), ((*hotspot).0 as i32, (*hotspot).1 as i32),
) )
.is_err() .is_err()
{ {
if let Err(err) = crtc::set_cursor(&*backend.dev.borrow(), *crtc, cursor) { if let Err(err) = backend.dev.borrow().set_cursor(*crtc, Some(cursor)) {
error!(self.logger, "Failed to reset cursor. Error: {}", err); error!(self.logger, "Failed to reset cursor. Error: {}", err);
} }
} }

View File

@ -1,7 +1,7 @@
use super::super::{Device, RawDevice, RawSurface, Surface}; use super::super::{Device, RawDevice, RawSurface, Surface};
use super::error::*; use super::error::*;
use drm::control::{connector, crtc, framebuffer, Mode, ResourceInfo}; use drm::control::{connector, crtc, framebuffer, Mode, Device as ControlDevice};
use gbm::{self, BufferObject, BufferObjectFlags, Format as GbmFormat, SurfaceBufferHandle}; use gbm::{self, BufferObject, BufferObjectFlags, Format as GbmFormat, SurfaceBufferHandle};
use image::{ImageBuffer, Rgba}; use image::{ImageBuffer, Rgba};
@ -16,12 +16,12 @@ use crate::backend::graphics::SwapBuffersError;
pub(super) struct GbmSurfaceInternal<D: RawDevice + 'static> { pub(super) struct GbmSurfaceInternal<D: RawDevice + 'static> {
pub(super) dev: Rc<RefCell<gbm::Device<D>>>, pub(super) dev: Rc<RefCell<gbm::Device<D>>>,
pub(super) surface: RefCell<gbm::Surface<framebuffer::Info>>, pub(super) surface: RefCell<gbm::Surface<framebuffer::Handle>>,
pub(super) crtc: <D as Device>::Surface, pub(super) crtc: <D as Device>::Surface,
pub(super) cursor: Cell<(BufferObject<()>, (u32, u32))>, pub(super) cursor: Cell<(BufferObject<()>, (u32, u32))>,
pub(super) current_frame_buffer: Cell<Option<framebuffer::Info>>, pub(super) current_frame_buffer: Cell<Option<framebuffer::Handle>>,
pub(super) front_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>, pub(super) front_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Handle>>>,
pub(super) next_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>, pub(super) next_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Handle>>>,
pub(super) recreated: Cell<bool>, pub(super) recreated: Cell<bool>,
pub(super) logger: ::slog::Logger, pub(super) logger: ::slog::Logger,
} }
@ -67,7 +67,8 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
let fb = if let Some(info) = maybe_fb { let fb = if let Some(info) = maybe_fb {
info info
} else { } else {
let fb = framebuffer::create(&self.crtc, &*next_bo).map_err(|_| SwapBuffersError::ContextLost)?; let fb = self.crtc.add_planar_framebuffer(&*next_bo, &[0; 4], 0)
.map_err(|_| SwapBuffersError::ContextLost)?;
next_bo.set_userdata(fb).unwrap(); next_bo.set_userdata(fb).unwrap();
fb fb
}; };
@ -76,13 +77,13 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
if self.recreated.get() { if self.recreated.get() {
debug!(self.logger, "Commiting new state"); debug!(self.logger, "Commiting new state");
self.crtc self.crtc
.commit(fb.handle()) .commit(fb)
.map_err(|_| SwapBuffersError::ContextLost)?; .map_err(|_| SwapBuffersError::ContextLost)?;
self.recreated.set(false); self.recreated.set(false);
} }
trace!(self.logger, "Queueing Page flip"); trace!(self.logger, "Queueing Page flip");
self.crtc.page_flip(fb.handle())?; RawSurface::page_flip(&self.crtc, fb)?;
self.current_frame_buffer.set(Some(fb)); self.current_frame_buffer.set(Some(fb));
@ -108,7 +109,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
// Clean up buffers // Clean up buffers
if let Some(Ok(Some(fb))) = self.next_buffer.take().map(|mut bo| bo.take_userdata()) { if let Some(Ok(Some(fb))) = self.next_buffer.take().map(|mut bo| bo.take_userdata()) {
if let Err(err) = framebuffer::destroy(&self.crtc, fb.handle()) { if let Err(err) = self.crtc.destroy_framebuffer(fb) {
warn!( warn!(
self.logger, self.logger,
"Error releasing old back_buffer framebuffer: {:?}", err "Error releasing old back_buffer framebuffer: {:?}", err
@ -117,7 +118,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
} }
if let Some(Ok(Some(fb))) = self.front_buffer.take().map(|mut bo| bo.take_userdata()) { if let Some(Ok(Some(fb))) = self.front_buffer.take().map(|mut bo| bo.take_userdata()) {
if let Err(err) = framebuffer::destroy(&self.crtc, fb.handle()) { if let Err(err) = self.crtc.destroy_framebuffer(fb) {
warn!( warn!(
self.logger, self.logger,
"Error releasing old front_buffer framebuffer: {:?}", err "Error releasing old front_buffer framebuffer: {:?}", err
@ -264,7 +265,7 @@ impl<D: RawDevice + 'static> Drop for GbmSurfaceInternal<D> {
} }
} { } {
// ignore failure at this point // ignore failure at this point
let _ = framebuffer::destroy(&self.crtc, fb.handle()); let _ = self.crtc.destroy_framebuffer(fb);
} }
if let Ok(Some(fb)) = { if let Ok(Some(fb)) = {
@ -275,7 +276,7 @@ impl<D: RawDevice + 'static> Drop for GbmSurfaceInternal<D> {
} }
} { } {
// ignore failure at this point // ignore failure at this point
let _ = framebuffer::destroy(&self.crtc, fb.handle()); let _ = self.crtc.destroy_framebuffer(fb);
} }
} }
} }

View File

@ -44,7 +44,7 @@ error_chain! {
#[doc = "No encoder was found for a given connector on the set crtc"] #[doc = "No encoder was found for a given connector on the set crtc"]
NoSuitableEncoder(connector: connector::Info, crtc: crtc::Handle) { NoSuitableEncoder(connector: connector::Info, crtc: crtc::Handle) {
description("No encoder found for given connector on set crtc"), description("No encoder found for given connector on set crtc"),
display("No encoder found for the given connector '{:?}' on the set crtc ({:?})", connector.connector_type(), crtc), display("No encoder found for the given connector '{:?}' on the set crtc ({:?})", connector.interface(), crtc),
} }
} }

View File

@ -10,8 +10,9 @@
use super::{DevPath, Device, DeviceHandler, RawDevice}; use super::{DevPath, Device, DeviceHandler, RawDevice};
use drm::control::{connector, crtc, encoder, Device as ControlDevice, ResourceHandles, ResourceInfo}; use drm::control::{connector, crtc, encoder, framebuffer, plane, Device as ControlDevice, Event, ResourceHandles};
use drm::Device as BasicDevice; use drm::{Device as BasicDevice, SystemError as DrmError};
use failure::ResultExt as FailureResultExt;
use nix::libc::dev_t; use nix::libc::dev_t;
use nix::sys::stat::fstat; use nix::sys::stat::fstat;
@ -65,12 +66,11 @@ impl<A: AsRawFd + 'static> Drop for Dev<A> {
// so that getty will be visible. // so that getty will be visible.
let old_state = self.old_state.clone(); let old_state = self.old_state.clone();
for (handle, (info, connectors)) in old_state { for (handle, (info, connectors)) in old_state {
if let Err(err) = crtc::set( if let Err(err) = self.set_crtc(
&*self,
handle, handle,
info.fb(), info.framebuffer(),
&connectors,
info.position(), info.position(),
&connectors,
info.mode(), info.mode(),
) { ) {
error!(self.logger, "Failed to reset crtc ({:?}). Error: {}", handle, err); error!(self.logger, "Failed to reset crtc ({:?}). Error: {}", handle, err);
@ -78,7 +78,7 @@ impl<A: AsRawFd + 'static> Drop for Dev<A> {
} }
} }
if self.priviledged { if self.priviledged {
if let Err(err) = self.drop_master() { if let Err(err) = self.release_master_lock() {
error!(self.logger, "Failed to drop drm master state. Error: {}", err); error!(self.logger, "Failed to drop drm master state. Error: {}", err);
} }
} }
@ -111,25 +111,25 @@ impl<A: AsRawFd + 'static> LegacyDrmDevice<A> {
}; };
// we want to modeset, so we better be the master, if we run via a tty session // we want to modeset, so we better be the master, if we run via a tty session
if dev.set_master().is_err() { if dev.acquire_master_lock().is_err() {
warn!(log, "Unable to become drm master, assuming unpriviledged mode"); warn!(log, "Unable to become drm master, assuming unpriviledged mode");
dev.priviledged = false; dev.priviledged = false;
}; };
// enumerate (and save) the current device state // enumerate (and save) the current device state
let res_handles = ControlDevice::resource_handles(&dev).chain_err(|| { let res_handles = ControlDevice::resource_handles(&dev).compat().chain_err(|| {
ErrorKind::DrmDev(format!("Error loading drm resources on {:?}", dev.dev_path())) ErrorKind::DrmDev(format!("Error loading drm resources on {:?}", dev.dev_path()))
})?; })?;
for &con in res_handles.connectors() { for &con in res_handles.connectors() {
let con_info = connector::Info::load_from_device(&dev, con).chain_err(|| { let con_info = dev.get_connector(con).compat().chain_err(|| {
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", dev.dev_path())) ErrorKind::DrmDev(format!("Error loading connector info on {:?}", dev.dev_path()))
})?; })?;
if let Some(enc) = con_info.current_encoder() { if let Some(enc) = con_info.current_encoder() {
let enc_info = encoder::Info::load_from_device(&dev, enc).chain_err(|| { let enc_info = dev.get_encoder(enc).compat().chain_err(|| {
ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", dev.dev_path())) ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", dev.dev_path()))
})?; })?;
if let Some(crtc) = enc_info.current_crtc() { if let Some(crtc) = enc_info.crtc() {
let info = crtc::Info::load_from_device(&dev, crtc).chain_err(|| { let info = dev.get_crtc(crtc).compat().chain_err(|| {
ErrorKind::DrmDev(format!("Error loading crtc info on {:?}", dev.dev_path())) ErrorKind::DrmDev(format!("Error loading crtc info on {:?}", dev.dev_path()))
})?; })?;
dev.old_state dev.old_state
@ -187,24 +187,24 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
// Try to enumarate the current state to set the initial state variable correctly // Try to enumarate the current state to set the initial state variable correctly
let crtc_info = crtc::Info::load_from_device(self, crtc) let crtc_info = self.get_crtc(crtc).compat()
.chain_err(|| ErrorKind::DrmDev(format!("Error loading crtc info on {:?}", self.dev_path())))?; .chain_err(|| ErrorKind::DrmDev(format!("Error loading crtc info on {:?}", self.dev_path())))?;
let mode = crtc_info.mode(); let mode = crtc_info.mode();
let mut connectors = HashSet::new(); let mut connectors = HashSet::new();
let res_handles = ControlDevice::resource_handles(self).chain_err(|| { let res_handles = ControlDevice::resource_handles(self).compat().chain_err(|| {
ErrorKind::DrmDev(format!("Error loading drm resources on {:?}", self.dev_path())) ErrorKind::DrmDev(format!("Error loading drm resources on {:?}", self.dev_path()))
})?; })?;
for &con in res_handles.connectors() { for &con in res_handles.connectors() {
let con_info = connector::Info::load_from_device(self, con).chain_err(|| { let con_info = self.get_connector(con).compat().chain_err(|| {
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path())) ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path()))
})?; })?;
if let Some(enc) = con_info.current_encoder() { if let Some(enc) = con_info.current_encoder() {
let enc_info = encoder::Info::load_from_device(self, enc).chain_err(|| { let enc_info = self.get_encoder(enc).compat().chain_err(|| {
ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", self.dev_path())) ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", self.dev_path()))
})?; })?;
if let Some(current_crtc) = enc_info.current_crtc() { if let Some(current_crtc) = enc_info.crtc() {
if crtc == current_crtc { if crtc == current_crtc {
connectors.insert(con); connectors.insert(con);
} }
@ -226,10 +226,10 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
} }
fn process_events(&mut self) { fn process_events(&mut self) {
match crtc::receive_events(self) { match self.receive_events() {
Ok(events) => { Ok(events) => {
for event in events { for event in events {
if let crtc::Event::PageFlip(event) = event { if let Event::PageFlip(event) = event {
if self.active.load(Ordering::SeqCst) { if self.active.load(Ordering::SeqCst) {
if self if self
.backends .backends
@ -254,7 +254,7 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
Err(err) => { Err(err) => {
if let Some(handler) = self.handler.as_ref() { if let Some(handler) = self.handler.as_ref() {
handler.borrow_mut().error( handler.borrow_mut().error(
ResultExt::<()>::chain_err(Err(err), || { ResultExt::<()>::chain_err(Err(err).compat(), || {
ErrorKind::DrmDev(format!("Error processing drm events on {:?}", self.dev_path())) ErrorKind::DrmDev(format!("Error processing drm events on {:?}", self.dev_path()))
}) })
.unwrap_err(), .unwrap_err(),
@ -264,14 +264,25 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
} }
} }
fn resource_info<T: ResourceInfo>(&self, handle: T::Handle) -> Result<T> { fn resource_handles(&self) -> Result<ResourceHandles> {
T::load_from_device(self, handle) ControlDevice::resource_handles(self).compat()
.chain_err(|| ErrorKind::DrmDev(format!("Error loading resource info on {:?}", self.dev_path()))) .chain_err(|| ErrorKind::DrmDev(format!("Error loading resource info on {:?}", self.dev_path())))
} }
fn resource_handles(&self) -> Result<ResourceHandles> { fn get_connector_info(&self, conn: connector::Handle) -> std::result::Result<connector::Info, DrmError> {
ControlDevice::resource_handles(self) self.get_connector(conn)
.chain_err(|| ErrorKind::DrmDev(format!("Error loading resource info on {:?}", self.dev_path()))) }
fn get_crtc_info(&self, crtc: crtc::Handle) -> std::result::Result<crtc::Info, DrmError> {
self.get_crtc(crtc)
}
fn get_encoder_info(&self, enc: encoder::Handle) -> std::result::Result<encoder::Info, DrmError> {
self.get_encoder(enc)
}
fn get_framebuffer_info(&self, fb: framebuffer::Handle) -> std::result::Result<framebuffer::Info, DrmError> {
self.get_framebuffer(fb)
}
fn get_plane_info(&self, plane: plane::Handle) -> std::result::Result<plane::Info, DrmError> {
self.get_plane(plane)
} }
} }

View File

@ -3,7 +3,7 @@
//! to an open [`Session`](::backend::session::Session). //! to an open [`Session`](::backend::session::Session).
//! //!
use drm::control::crtc; use drm::control::{crtc, Device as ControlDevice};
use drm::Device as BasicDevice; use drm::Device as BasicDevice;
use nix::libc::dev_t; use nix::libc::dev_t;
use nix::sys::stat; use nix::sys::stat;
@ -54,14 +54,14 @@ impl<A: AsRawFd + 'static> SessionObserver for LegacyDrmDeviceObserver<A> {
for surface in backends.borrow().values().filter_map(Weak::upgrade) { for surface in backends.borrow().values().filter_map(Weak::upgrade) {
// other ttys that use no cursor, might not clear it themselves. // other ttys that use no cursor, might not clear it themselves.
// This makes sure our cursor won't stay visible. // This makes sure our cursor won't stay visible.
let _ = crtc::clear_cursor(&*device, surface.crtc); let _ = (*device).set_cursor(surface.crtc, Option::<&drm::control::dumbbuffer::DumbBuffer>::None);
} }
} }
} }
self.active.store(false, Ordering::SeqCst); self.active.store(false, Ordering::SeqCst);
if self.priviledged { if self.priviledged {
if let Some(device) = self.dev.upgrade() { if let Some(device) = self.dev.upgrade() {
if let Err(err) = device.drop_master() { if let Err(err) = device.release_master_lock() {
error!(self.logger, "Failed to drop drm master state. Error: {}", err); error!(self.logger, "Failed to drop drm master state. Error: {}", err);
} }
} }
@ -83,7 +83,7 @@ impl<A: AsRawFd + 'static> SessionObserver for LegacyDrmDeviceObserver<A> {
self.active.store(true, Ordering::SeqCst); self.active.store(true, Ordering::SeqCst);
if self.priviledged { if self.priviledged {
if let Some(device) = self.dev.upgrade() { if let Some(device) = self.dev.upgrade() {
if let Err(err) = device.set_master() { if let Err(err) = device.acquire_master_lock() {
crit!(self.logger, "Failed to acquire drm master again. Error: {}", err); crit!(self.logger, "Failed to acquire drm master again. Error: {}", err);
} }
} }

View File

@ -1,6 +1,7 @@
use drm::buffer::Buffer; use drm::buffer::Buffer;
use drm::control::{connector, crtc, encoder, framebuffer, Device as ControlDevice, Mode, ResourceInfo}; use drm::control::{connector, crtc, dumbbuffer::DumbBuffer, encoder, framebuffer, Device as ControlDevice, Mode, PageFlipFlags};
use drm::Device as BasicDevice; use drm::Device as BasicDevice;
use failure::ResultExt as FailureResultExt;
use std::collections::HashSet; use std::collections::HashSet;
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
@ -42,7 +43,8 @@ impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for LegacyDrmSurfaceInternal<A>
fn set_cursor_position(&self, x: u32, y: u32) -> Result<()> { fn set_cursor_position(&self, x: u32, y: u32) -> Result<()> {
trace!(self.logger, "Move the cursor to {},{}", x, y); trace!(self.logger, "Move the cursor to {},{}", x, y);
crtc::move_cursor(self, self.crtc, (x as i32, y as i32)) self.move_cursor(self.crtc, (x as i32, y as i32))
.compat()
.chain_err(|| ErrorKind::DrmDev(format!("Error moving cursor on {:?}", self.dev_path()))) .chain_err(|| ErrorKind::DrmDev(format!("Error moving cursor on {:?}", self.dev_path())))
} }
@ -52,8 +54,9 @@ impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for LegacyDrmSurfaceInternal<A>
{ {
trace!(self.logger, "Setting the new imported cursor"); trace!(self.logger, "Setting the new imported cursor");
if crtc::set_cursor2(self, self.crtc, buffer, (hotspot.0 as i32, hotspot.1 as i32)).is_err() { if self.set_cursor2(self.crtc, Some(buffer), (hotspot.0 as i32, hotspot.1 as i32)).is_err() {
crtc::set_cursor(self, self.crtc, buffer) self.set_cursor(self.crtc, Some(buffer))
.compat()
.chain_err(|| ErrorKind::DrmDev(format!("Failed to set cursor on {:?}", self.dev_path())))?; .chain_err(|| ErrorKind::DrmDev(format!("Failed to set cursor on {:?}", self.dev_path())))?;
} }
@ -85,8 +88,8 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurfaceInternal<A> {
self.pending.read().unwrap().mode self.pending.read().unwrap().mode
} }
fn add_connector(&self, connector: connector::Handle) -> Result<()> { fn add_connector(&self, conn: connector::Handle) -> Result<()> {
let info = connector::Info::load_from_device(self, connector).chain_err(|| { let info = self.get_connector(conn).compat().chain_err(|| {
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path())) ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path()))
})?; })?;
@ -98,15 +101,17 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurfaceInternal<A> {
let encoders = info let encoders = info
.encoders() .encoders()
.iter() .iter()
.filter(|enc| enc.is_some())
.map(|enc| enc.unwrap())
.map(|encoder| { .map(|encoder| {
encoder::Info::load_from_device(self, *encoder).chain_err(|| { self.get_encoder(encoder).compat().chain_err(|| {
ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", self.dev_path())) ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", self.dev_path()))
}) })
}) })
.collect::<Result<Vec<encoder::Info>>>()?; .collect::<Result<Vec<encoder::Info>>>()?;
// and if any encoder supports the selected crtc // and if any encoder supports the selected crtc
let resource_handles = self.resource_handles().chain_err(|| { let resource_handles = self.resource_handles().compat().chain_err(|| {
ErrorKind::DrmDev(format!("Error loading resources on {:?}", self.dev_path())) ErrorKind::DrmDev(format!("Error loading resources on {:?}", self.dev_path()))
})?; })?;
if !encoders if !encoders
@ -117,7 +122,7 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurfaceInternal<A> {
bail!(ErrorKind::NoSuitableEncoder(info, self.crtc)); bail!(ErrorKind::NoSuitableEncoder(info, self.crtc));
} }
pending.connectors.insert(connector); pending.connectors.insert(conn);
Ok(()) Ok(())
} else { } else {
bail!(ErrorKind::ModeNotSuitable(pending.mode.unwrap())); bail!(ErrorKind::ModeNotSuitable(pending.mode.unwrap()));
@ -135,11 +140,14 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurfaceInternal<A> {
// check the connectors to see if this mode is supported // check the connectors to see if this mode is supported
if let Some(mode) = mode { if let Some(mode) = mode {
for connector in &pending.connectors { for connector in &pending.connectors {
let info = connector::Info::load_from_device(self, *connector).chain_err(|| { if !self.get_connector(*connector)
.compat()
.chain_err(|| {
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path())) ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path()))
})?; })?
.modes()
if !info.modes().contains(&mode) { .contains(&mode)
{
bail!(ErrorKind::ModeNotSuitable(mode)); bail!(ErrorKind::ModeNotSuitable(mode));
} }
} }
@ -165,16 +173,16 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
let added = pending.connectors.difference(&current.connectors); let added = pending.connectors.difference(&current.connectors);
for conn in removed { for conn in removed {
if let Ok(info) = connector::Info::load_from_device(self, *conn) { if let Ok(info) = self.get_connector(*conn) {
info!(self.logger, "Removing connector: {:?}", info.connector_type()); info!(self.logger, "Removing connector: {:?}", info.interface());
} else { } else {
info!(self.logger, "Removing unknown connector"); info!(self.logger, "Removing unknown connector");
} }
} }
for conn in added { for conn in added {
if let Ok(info) = connector::Info::load_from_device(self, *conn) { if let Ok(info) = self.get_connector(*conn) {
info!(self.logger, "Adding connector: {:?}", info.connector_type()); info!(self.logger, "Adding connector: {:?}", info.interface());
} else { } else {
info!(self.logger, "Adding unknown connector"); info!(self.logger, "Adding unknown connector");
} }
@ -190,18 +198,18 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
} }
debug!(self.logger, "Setting screen"); debug!(self.logger, "Setting screen");
crtc::set( self.set_crtc(
self,
self.crtc, self.crtc,
framebuffer, Some(framebuffer),
(0, 0),
&pending &pending
.connectors .connectors
.iter() .iter()
.copied() .copied()
.collect::<Vec<connector::Handle>>(), .collect::<Vec<connector::Handle>>(),
(0, 0),
pending.mode, pending.mode,
) )
.compat()
.chain_err(|| { .chain_err(|| {
ErrorKind::DrmDev(format!( ErrorKind::DrmDev(format!(
"Error setting crtc {:?} on {:?}", "Error setting crtc {:?} on {:?}",
@ -218,12 +226,14 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
fn page_flip(&self, framebuffer: framebuffer::Handle) -> ::std::result::Result<(), SwapBuffersError> { fn page_flip(&self, framebuffer: framebuffer::Handle) -> ::std::result::Result<(), SwapBuffersError> {
trace!(self.logger, "Queueing Page flip"); trace!(self.logger, "Queueing Page flip");
crtc::page_flip( ControlDevice::page_flip(
self, self,
self.crtc, self.crtc,
framebuffer, framebuffer,
&[crtc::PageFlipFlags::PageFlipEvent], &[PageFlipFlags::PageFlipEvent],
None,
) )
.map_err(|x| dbg!(x))
.map_err(|_| SwapBuffersError::ContextLost) .map_err(|_| SwapBuffersError::ContextLost)
} }
} }
@ -231,7 +241,7 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
impl<A: AsRawFd + 'static> Drop for LegacyDrmSurfaceInternal<A> { impl<A: AsRawFd + 'static> Drop for LegacyDrmSurfaceInternal<A> {
fn drop(&mut self) { fn drop(&mut self) {
// ignore failure at this point // ignore failure at this point
let _ = crtc::clear_cursor(self, self.crtc); let _ = self.set_cursor(self.crtc, Option::<&DumbBuffer>::None);
} }
} }
@ -310,6 +320,6 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurface<A> {
} }
fn page_flip(&self, framebuffer: framebuffer::Handle) -> ::std::result::Result<(), SwapBuffersError> { fn page_flip(&self, framebuffer: framebuffer::Handle) -> ::std::result::Result<(), SwapBuffersError> {
self.0.page_flip(framebuffer) RawSurface::page_flip(&*self.0, framebuffer)
} }
} }

View File

@ -36,8 +36,9 @@
//! //!
use drm::{ use drm::{
control::{connector, crtc, framebuffer, Device as ControlDevice, Mode, ResourceHandles, ResourceInfo}, control::{connector, crtc, encoder, plane, framebuffer, Device as ControlDevice, Mode, ResourceHandles},
Device as BasicDevice, Device as BasicDevice,
SystemError as DrmError,
}; };
use nix::libc::dev_t; use nix::libc::dev_t;
@ -110,16 +111,15 @@ pub trait Device: AsRawFd + DevPath {
/// to synchronize your rendering to the vblank events of the open crtc's /// to synchronize your rendering to the vblank events of the open crtc's
fn process_events(&mut self); fn process_events(&mut self);
/// Load the resource from a [`Device`] given its
/// [`ResourceHandle`](drm::control::ResourceHandle)
fn resource_info<T: ResourceInfo>(
&self,
handle: T::Handle,
) -> Result<T, <Self::Surface as Surface>::Error>;
/// Attempts to acquire a copy of the [`Device`]'s /// Attempts to acquire a copy of the [`Device`]'s
/// [`ResourceHandle`](drm::control::ResourceHandle) /// [`ResourceHandle`](drm::control::ResourceHandle)
fn resource_handles(&self) -> Result<ResourceHandles, <Self::Surface as Surface>::Error>; fn resource_handles(&self) -> Result<ResourceHandles, <Self::Surface as Surface>::Error>;
fn get_connector_info(&self, conn: connector::Handle) -> Result<connector::Info, DrmError>;
fn get_crtc_info(&self, crtc: crtc::Handle) -> Result<crtc::Info, DrmError>;
fn get_encoder_info(&self, enc: encoder::Handle) -> Result<encoder::Info, DrmError>;
fn get_framebuffer_info(&self, fb: framebuffer::Handle) -> Result<framebuffer::Info, DrmError>;
fn get_plane_info(&self, plane: plane::Handle) -> Result<plane::Info, DrmError>;
} }
/// Marker trait for [`Device`]s able to provide [`RawSurface`]s /// Marker trait for [`Device`]s able to provide [`RawSurface`]s

View File

@ -78,7 +78,7 @@ use wayland_server::{protocol::wl_buffer, Display, Global, Main, Filter};
/// Representation of a Dmabuf format, as advertized to the client /// Representation of a Dmabuf format, as advertized to the client
pub struct Format { pub struct Format {
/// The format identifier. /// The format identifier.
pub format: ::drm::buffer::PixelFormat, pub format: ::drm::buffer::format::PixelFormat,
/// The supported dmabuf layout modifier. /// The supported dmabuf layout modifier.
/// ///
/// This is an opaque token. Drivers use this token to express tiling, compression, etc. driver-specific /// This is an opaque token. Drivers use this token to express tiling, compression, etc. driver-specific