commit
cceb9dabf4
|
@ -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"]
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(|| {
|
||||
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path()))
|
||||
})?;
|
||||
|
||||
if !info.modes().contains(&mode) {
|
||||
if !self.get_connector(*connector)
|
||||
.compat()
|
||||
.chain_err(|| {
|
||||
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path()))
|
||||
})?
|
||||
.modes()
|
||||
.contains(&mode)
|
||||
{
|
||||
bail!(ErrorKind::ModeNotSuitable(mode));
|
||||
}
|
||||
}
|
||||
|
@ -165,16 +173,16 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
|
|||
let added = pending.connectors.difference(¤t.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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue