commit
cceb9dabf4
|
@ -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"]
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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")]
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(¤t.connectors);
|
let added = pending.connectors.difference(¤t.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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue