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 }
calloop = "0.5.1"
bitflags = "1"
nix = "0.13"
nix = "0.15"
xkbcommon = "0.4.0"
tempfile = "3.0"
slog = "2.1.1"
@ -24,8 +24,8 @@ slog-stdlog = "3.0.2"
libloading = "0.5.0"
wayland-client = { version = "0.23.4", features = ["egl"], optional = true }
winit = { version = "0.22.0", optional = true }
drm = { version = "^0.3.4", optional = true }
gbm = { version = "^0.5.0", optional = true, default-features = false, features = ["drm-support"] }
drm = { version = "^0.4.0", git = "https://github.com/drakulix/drm-rs", branch = "develop", optional = true }
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 }
input = { version = "0.4.1", 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 }
error-chain = "0.12.0"
lazy_static = "1.0.0"
failure = { version = "0.1.5", optional = true }
[dev-dependencies]
slog-term = "2.3"
@ -45,7 +46,7 @@ gl_generator = { version = "0.10", optional = true }
[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"]
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_gbm = ["backend_drm", "gbm", "image"]
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
.connectors()
.iter()
.map(|conn| device.resource_info::<ConnectorInfo>(*conn).unwrap())
.filter(|conn| conn.connection_state() == ConnectorState::Connected)
.inspect(|conn| info!(logger, "Connected: {:?}", conn.connector_type()))
.map(|conn| device.get_connector_info(*conn).unwrap())
.filter(|conn| conn.state() == ConnectorState::Connected)
.inspect(|conn| info!(logger, "Connected: {:?}", conn.interface()))
.collect();
let mut backends = HashMap::new();
@ -335,7 +335,8 @@ impl<S: SessionNotifier, Data: 'static> UdevHandlerImpl<S, Data> {
let encoder_infos = connector_info
.encoders()
.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>>();
for encoder_info in encoder_infos {
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {

View File

@ -13,12 +13,12 @@ use smithay::{
reexports::{
calloop::EventLoop,
drm::{
buffer::PixelFormat,
buffer::format::PixelFormat,
control::{
connector::{self, State as ConnectorState},
crtc,
dumbbuffer::DumbBuffer,
encoder, framebuffer, Device as ControlDevice, ResourceInfo,
encoder, framebuffer, Device as ControlDevice,
},
},
},
@ -50,16 +50,17 @@ fn main() {
let connector_info = res_handles
.connectors()
.iter()
.map(|conn| Device::resource_info::<connector::Info>(&device, *conn).unwrap())
.find(|conn| conn.connection_state() == ConnectorState::Connected)
.map(|conn| device.get_connector_info(*conn).unwrap())
.find(|conn| conn.state() == ConnectorState::Connected)
.unwrap();
// 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
let crtc = encoder_info
.current_crtc()
.crtc()
// or use the first one that is compatible with the encoder
.unwrap_or_else(|| {
*res_handles
@ -89,16 +90,14 @@ fn main() {
* But they are very slow, this is just for demonstration purposes.
*/
let (w, h) = mode.size();
let front_buffer =
DumbBuffer::create_from_device(&device, (w as u32, h as u32), PixelFormat::XRGB8888).unwrap();
let front_framebuffer = device.create_framebuffer(&front_buffer).unwrap();
let back_buffer =
DumbBuffer::create_from_device(&device, (w as u32, h as u32), PixelFormat::XRGB8888).unwrap();
let back_framebuffer = device.create_framebuffer(&back_buffer).unwrap();
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.handle(),
front: (front_buffer, front_framebuffer.clone()),
current: front_framebuffer,
front: (front_buffer, front_framebuffer),
back: (back_buffer, back_framebuffer),
surface: surface.clone(),
});
@ -113,17 +112,17 @@ fn main() {
// Start rendering
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
event_loop.run(None, &mut (), |_| {}).unwrap();
}
pub struct DrmHandlerImpl {
front: (DumbBuffer, framebuffer::Info),
back: (DumbBuffer, framebuffer::Info),
front: (DumbBuffer, framebuffer::Handle),
back: (DumbBuffer, framebuffer::Handle),
current: framebuffer::Handle,
surface: Rc<LegacyDrmSurface<File>>,
}
@ -134,12 +133,12 @@ impl DeviceHandler for DrmHandlerImpl {
fn vblank(&mut self, _crtc: crtc::Handle) {
{
// Swap and map buffer
let mut mapping = if self.current == self.front.1.handle() {
self.current = self.back.1.handle();
self.back.0.map(&*self.surface).unwrap()
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.handle();
self.front.0.map(&*self.surface).unwrap()
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.
@ -149,7 +148,7 @@ impl DeviceHandler for DrmHandlerImpl {
*x = 128;
}
}
self.surface.page_flip(self.current).unwrap();
RawSurface::page_flip(&*self.surface, self.current).unwrap();
}
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.
//!
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 std::os::unix::io::{AsRawFd, RawFd};
use std::rc::Rc;
@ -166,19 +167,28 @@ where
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> {
self.dev
.borrow()
.resource_handles()
.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")]

View File

@ -9,9 +9,11 @@
//! 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 nix::libc::dev_t;
@ -185,19 +187,29 @@ impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D> {
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> {
self.dev
.borrow()
.resource_handles()
.compat()
.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> {

View File

@ -3,7 +3,7 @@
//! to an open [`Session`](::backend::session::Session).
//!
use drm::control::{crtc, Device as ControlDevice, ResourceInfo};
use drm::control::crtc;
use gbm::BufferObject;
use std::cell::RefCell;
use std::collections::HashMap;
@ -19,14 +19,14 @@ use crate::backend::session::{AsSessionObserver, SessionObserver};
/// created from.
pub struct GbmDeviceObserver<
S: SessionObserver + 'static,
D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static,
D: RawDevice + ::drm::control::Device + AsSessionObserver<S> + 'static,
> {
observer: S,
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<GbmSurfaceInternal<D>>>>>,
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>
{
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>
{
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
.current_frame_buffer
.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);
}
// reset cursor
{
use ::drm::control::Device;
let &(ref cursor, ref hotspot): &(BufferObject<()>, (u32, u32)) =
unsafe { &*backend.cursor.as_ptr() };
if crtc::set_cursor2(
&*backend.dev.borrow(),
if backend.dev.borrow().set_cursor2(
*crtc,
cursor,
Some(cursor),
((*hotspot).0 as i32, (*hotspot).1 as i32),
)
.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);
}
}

View File

@ -1,7 +1,7 @@
use super::super::{Device, RawDevice, RawSurface, Surface};
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 image::{ImageBuffer, Rgba};
@ -16,12 +16,12 @@ use crate::backend::graphics::SwapBuffersError;
pub(super) struct GbmSurfaceInternal<D: RawDevice + 'static> {
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) cursor: Cell<(BufferObject<()>, (u32, u32))>,
pub(super) current_frame_buffer: Cell<Option<framebuffer::Info>>,
pub(super) front_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>,
pub(super) next_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>,
pub(super) current_frame_buffer: Cell<Option<framebuffer::Handle>>,
pub(super) front_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Handle>>>,
pub(super) next_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Handle>>>,
pub(super) recreated: Cell<bool>,
pub(super) logger: ::slog::Logger,
}
@ -67,7 +67,8 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
let fb = if let Some(info) = maybe_fb {
info
} 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();
fb
};
@ -76,13 +77,13 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
if self.recreated.get() {
debug!(self.logger, "Commiting new state");
self.crtc
.commit(fb.handle())
.commit(fb)
.map_err(|_| SwapBuffersError::ContextLost)?;
self.recreated.set(false);
}
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));
@ -108,7 +109,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
// Clean up buffers
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!(
self.logger,
"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 Err(err) = framebuffer::destroy(&self.crtc, fb.handle()) {
if let Err(err) = self.crtc.destroy_framebuffer(fb) {
warn!(
self.logger,
"Error releasing old front_buffer framebuffer: {:?}", err
@ -264,7 +265,7 @@ impl<D: RawDevice + 'static> Drop for GbmSurfaceInternal<D> {
}
} {
// ignore failure at this point
let _ = framebuffer::destroy(&self.crtc, fb.handle());
let _ = self.crtc.destroy_framebuffer(fb);
}
if let Ok(Some(fb)) = {
@ -275,7 +276,7 @@ impl<D: RawDevice + 'static> Drop for GbmSurfaceInternal<D> {
}
} {
// 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"]
NoSuitableEncoder(connector: connector::Info, crtc: crtc::Handle) {
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 drm::control::{connector, crtc, encoder, Device as ControlDevice, ResourceHandles, ResourceInfo};
use drm::Device as BasicDevice;
use drm::control::{connector, crtc, encoder, framebuffer, plane, Device as ControlDevice, Event, ResourceHandles};
use drm::{Device as BasicDevice, SystemError as DrmError};
use failure::ResultExt as FailureResultExt;
use nix::libc::dev_t;
use nix::sys::stat::fstat;
@ -65,12 +66,11 @@ impl<A: AsRawFd + 'static> Drop for Dev<A> {
// so that getty will be visible.
let old_state = self.old_state.clone();
for (handle, (info, connectors)) in old_state {
if let Err(err) = crtc::set(
&*self,
if let Err(err) = self.set_crtc(
handle,
info.fb(),
&connectors,
info.framebuffer(),
info.position(),
&connectors,
info.mode(),
) {
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 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);
}
}
@ -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
if dev.set_master().is_err() {
if dev.acquire_master_lock().is_err() {
warn!(log, "Unable to become drm master, assuming unpriviledged mode");
dev.priviledged = false;
};
// 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()))
})?;
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()))
})?;
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()))
})?;
if let Some(crtc) = enc_info.current_crtc() {
let info = crtc::Info::load_from_device(&dev, crtc).chain_err(|| {
if let Some(crtc) = enc_info.crtc() {
let info = dev.get_crtc(crtc).compat().chain_err(|| {
ErrorKind::DrmDev(format!("Error loading crtc info on {:?}", dev.dev_path()))
})?;
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
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())))?;
let mode = crtc_info.mode();
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()))
})?;
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()))
})?;
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()))
})?;
if let Some(current_crtc) = enc_info.current_crtc() {
if let Some(current_crtc) = enc_info.crtc() {
if crtc == current_crtc {
connectors.insert(con);
}
@ -226,10 +226,10 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
}
fn process_events(&mut self) {
match crtc::receive_events(self) {
match self.receive_events() {
Ok(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
.backends
@ -254,7 +254,7 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
Err(err) => {
if let Some(handler) = self.handler.as_ref() {
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()))
})
.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> {
T::load_from_device(self, handle)
fn resource_handles(&self) -> Result<ResourceHandles> {
ControlDevice::resource_handles(self).compat()
.chain_err(|| ErrorKind::DrmDev(format!("Error loading resource info on {:?}", self.dev_path())))
}
fn resource_handles(&self) -> Result<ResourceHandles> {
ControlDevice::resource_handles(self)
.chain_err(|| ErrorKind::DrmDev(format!("Error loading resource info on {:?}", self.dev_path())))
fn get_connector_info(&self, conn: connector::Handle) -> std::result::Result<connector::Info, DrmError> {
self.get_connector(conn)
}
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).
//!
use drm::control::crtc;
use drm::control::{crtc, Device as ControlDevice};
use drm::Device as BasicDevice;
use nix::libc::dev_t;
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) {
// other ttys that use no cursor, might not clear it themselves.
// 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);
if self.priviledged {
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);
}
}
@ -83,7 +83,7 @@ impl<A: AsRawFd + 'static> SessionObserver for LegacyDrmDeviceObserver<A> {
self.active.store(true, Ordering::SeqCst);
if self.priviledged {
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);
}
}

View File

@ -1,6 +1,7 @@
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 failure::ResultExt as FailureResultExt;
use std::collections::HashSet;
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<()> {
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())))
}
@ -52,8 +54,9 @@ impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for LegacyDrmSurfaceInternal<A>
{
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() {
crtc::set_cursor(self, self.crtc, buffer)
if self.set_cursor2(self.crtc, Some(buffer), (hotspot.0 as i32, hotspot.1 as i32)).is_err() {
self.set_cursor(self.crtc, Some(buffer))
.compat()
.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
}
fn add_connector(&self, connector: connector::Handle) -> Result<()> {
let info = connector::Info::load_from_device(self, connector).chain_err(|| {
fn add_connector(&self, conn: connector::Handle) -> Result<()> {
let info = self.get_connector(conn).compat().chain_err(|| {
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
.encoders()
.iter()
.filter(|enc| enc.is_some())
.map(|enc| enc.unwrap())
.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()))
})
})
.collect::<Result<Vec<encoder::Info>>>()?;
// 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()))
})?;
if !encoders
@ -117,7 +122,7 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurfaceInternal<A> {
bail!(ErrorKind::NoSuitableEncoder(info, self.crtc));
}
pending.connectors.insert(connector);
pending.connectors.insert(conn);
Ok(())
} else {
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
if let Some(mode) = mode {
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()))
})?;
if !info.modes().contains(&mode) {
})?
.modes()
.contains(&mode)
{
bail!(ErrorKind::ModeNotSuitable(mode));
}
}
@ -165,16 +173,16 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
let added = pending.connectors.difference(&current.connectors);
for conn in removed {
if let Ok(info) = connector::Info::load_from_device(self, *conn) {
info!(self.logger, "Removing connector: {:?}", info.connector_type());
if let Ok(info) = self.get_connector(*conn) {
info!(self.logger, "Removing connector: {:?}", info.interface());
} else {
info!(self.logger, "Removing unknown connector");
}
}
for conn in added {
if let Ok(info) = connector::Info::load_from_device(self, *conn) {
info!(self.logger, "Adding connector: {:?}", info.connector_type());
if let Ok(info) = self.get_connector(*conn) {
info!(self.logger, "Adding connector: {:?}", info.interface());
} else {
info!(self.logger, "Adding unknown connector");
}
@ -190,18 +198,18 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
}
debug!(self.logger, "Setting screen");
crtc::set(
self,
self.set_crtc(
self.crtc,
framebuffer,
Some(framebuffer),
(0, 0),
&pending
.connectors
.iter()
.copied()
.collect::<Vec<connector::Handle>>(),
(0, 0),
pending.mode,
)
.compat()
.chain_err(|| {
ErrorKind::DrmDev(format!(
"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> {
trace!(self.logger, "Queueing Page flip");
crtc::page_flip(
ControlDevice::page_flip(
self,
self.crtc,
framebuffer,
&[crtc::PageFlipFlags::PageFlipEvent],
&[PageFlipFlags::PageFlipEvent],
None,
)
.map_err(|x| dbg!(x))
.map_err(|_| SwapBuffersError::ContextLost)
}
}
@ -231,7 +241,7 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
impl<A: AsRawFd + 'static> Drop for LegacyDrmSurfaceInternal<A> {
fn drop(&mut self) {
// 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> {
self.0.page_flip(framebuffer)
RawSurface::page_flip(&*self.0, framebuffer)
}
}

View File

@ -36,8 +36,9 @@
//!
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,
SystemError as DrmError,
};
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
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
/// [`ResourceHandle`](drm::control::ResourceHandle)
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

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
pub struct Format {
/// The format identifier.
pub format: ::drm::buffer::PixelFormat,
pub format: ::drm::buffer::format::PixelFormat,
/// The supported dmabuf layout modifier.
///
/// This is an opaque token. Drivers use this token to express tiling, compression, etc. driver-specific