drm: remove mode & connector arguments of create_surface

This commit is contained in:
Victor Brekenfeld 2018-12-02 20:07:39 +01:00
parent 99f9156f64
commit b160a91f8a
11 changed files with 113 additions and 154 deletions

View File

@ -38,7 +38,6 @@ use smithay::{
connector::{Info as ConnectorInfo, State as ConnectorState}, connector::{Info as ConnectorInfo, State as ConnectorState},
crtc, crtc,
encoder::Info as EncoderInfo, encoder::Info as EncoderInfo,
ResourceInfo,
}, },
image::{ImageBuffer, Rgba}, image::{ImageBuffer, Rgba},
input::Libinput, input::Libinput,
@ -283,11 +282,9 @@ impl<S: SessionNotifier, Data: 'static> UdevHandlerImpl<S, Data> {
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()) {
if !backends.contains_key(&crtc) { if !backends.contains_key(&crtc) {
let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.)
// create a backend
let renderer = GliumDrawer::init( let renderer = GliumDrawer::init(
device device
.create_surface(crtc, mode, vec![connector_info.handle()].into_iter()) .create_surface(crtc)
.unwrap(), .unwrap(),
egl_display.clone(), egl_display.clone(),
logger.clone(), logger.clone(),
@ -332,11 +329,9 @@ impl<S: SessionNotifier, Data: 'static> UdevHandlerImpl<S, Data> {
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()) {
if !backends.contains_key(&crtc) { if !backends.contains_key(&crtc) {
let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.)
// create a backend
let renderer = GliumDrawer::init( let renderer = GliumDrawer::init(
device device
.create_surface(crtc, mode, vec![connector_info.handle()].into_iter()) .create_surface(crtc)
.unwrap(), .unwrap(),
logger.clone(), logger.clone(),
); );

View File

@ -1,6 +1,5 @@
use drm::control::{connector, crtc, Mode, ResourceHandles, ResourceInfo}; use drm::control::{crtc, ResourceHandles, ResourceInfo};
use nix::libc::dev_t; use nix::libc::dev_t;
use std::iter::FromIterator;
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
use std::rc::Rc; use std::rc::Rc;
use wayland_server::Display; use wayland_server::Display;
@ -25,19 +24,19 @@ pub mod session;
/// Representation of an open gbm device to create rendering backends /// Representation of an open gbm device to create rendering backends
pub struct EglDevice< pub struct EglDevice<
B: Backend<Surface = <D as Device>::Surface> + 'static, B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B> + 'static, D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> where > where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface, <D as Device>::Surface: NativeSurface,
{ {
dev: Rc<EGLContext<B, D>>, dev: Rc<EGLContext<B, D>>,
logger: ::slog::Logger, logger: ::slog::Logger,
} }
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> AsRawFd impl<
for EglDevice<B, D> B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> AsRawFd for EglDevice<B, D>
where where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface, <D as Device>::Surface: NativeSurface,
{ {
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
@ -45,10 +44,11 @@ where
} }
} }
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> impl<
EglDevice<B, D> B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> EglDevice<B, D>
where where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface, <D as Device>::Surface: NativeSurface,
{ {
/// Create a new `EglGbmDrmDevice` from an open drm node /// Create a new `EglGbmDrmDevice` from an open drm node
@ -96,18 +96,18 @@ where
struct InternalDeviceHandler< struct InternalDeviceHandler<
B: Backend<Surface = <D as Device>::Surface> + 'static, B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B> + 'static, D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> where > where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface, <D as Device>::Surface: NativeSurface,
{ {
handler: Box<DeviceHandler<Device = EglDevice<B, D>> + 'static>, handler: Box<DeviceHandler<Device = EglDevice<B, D>> + 'static>,
} }
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> impl<
DeviceHandler for InternalDeviceHandler<B, D> B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> DeviceHandler for InternalDeviceHandler<B, D>
where where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface, <D as Device>::Surface: NativeSurface,
{ {
type Device = D; type Device = D;
@ -121,10 +121,11 @@ where
} }
} }
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> Device impl<
for EglDevice<B, D> B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> Device for EglDevice<B, D>
where where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface, <D as Device>::Surface: NativeSurface,
{ {
type Surface = EglSurface<B, D>; type Surface = EglSurface<B, D>;
@ -143,17 +144,10 @@ where
self.dev.borrow_mut().clear_handler() self.dev.borrow_mut().clear_handler()
} }
fn create_surface( fn create_surface(&mut self, crtc: crtc::Handle) -> Result<EglSurface<B, D>> {
&mut self,
crtc: crtc::Handle,
mode: Mode,
connectors: impl IntoIterator<Item = connector::Handle>,
) -> Result<EglSurface<B, D>> {
info!(self.logger, "Initializing EglSurface"); info!(self.logger, "Initializing EglSurface");
let surface = self let surface = self.dev.create_surface(crtc)?;
.dev
.create_surface((crtc, mode, Vec::from_iter(connectors)).into())?;
Ok(EglSurface { Ok(EglSurface {
dev: self.dev.clone(), dev: self.dev.clone(),
@ -181,10 +175,11 @@ where
} }
#[cfg(feature = "native_lib")] #[cfg(feature = "native_lib")]
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> impl<
EGLGraphicsBackend for EglDevice<B, D> B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> EGLGraphicsBackend for EglDevice<B, D>
where where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface, <D as Device>::Surface: NativeSurface,
{ {
fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> { fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> {
@ -192,10 +187,11 @@ where
} }
} }
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> impl<
Drop for EglDevice<B, D> B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> Drop for EglDevice<B, D>
where where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface, <D as Device>::Surface: NativeSurface,
{ {
fn drop(&mut self) { fn drop(&mut self) {

View File

@ -1,5 +1,5 @@
use drm::control::{connector, crtc, Mode};
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use drm::control::{crtc, connector, Mode};
use super::EglDevice; use super::EglDevice;
use backend::drm::Device; use backend::drm::Device;
@ -14,10 +14,9 @@ pub struct EglDeviceObserver<S: SessionObserver + 'static> {
impl< impl<
S: SessionObserver + 'static, S: SessionObserver + 'static,
B: Backend<Surface = <D as Device>::Surface> + 'static, B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B> + AsSessionObserver<S> + 'static, D: Device + NativeDisplay<B, Arguments = crtc::Handle> + AsSessionObserver<S> + 'static,
> AsSessionObserver<EglDeviceObserver<S>> for EglDevice<B, D> > AsSessionObserver<EglDeviceObserver<S>> for EglDevice<B, D>
where where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface, <D as Device>::Surface: NativeSurface,
{ {
fn observer(&mut self) -> EglDeviceObserver<S> { fn observer(&mut self) -> EglDeviceObserver<S> {

View File

@ -54,15 +54,15 @@ where
.chain_err(|| ErrorKind::UnderlyingBackendError) .chain_err(|| ErrorKind::UnderlyingBackendError)
} }
fn current_mode(&self) -> Mode { fn current_mode(&self) -> Option<Mode> {
self.surface.current_mode() self.surface.current_mode()
} }
fn pending_mode(&self) -> Mode { fn pending_mode(&self) -> Option<Mode> {
self.surface.pending_mode() self.surface.pending_mode()
} }
fn use_mode(&self, mode: Mode) -> Result<()> { fn use_mode(&self, mode: Option<Mode>) -> Result<()> {
self.surface self.surface
.use_mode(mode) .use_mode(mode)
.chain_err(|| ErrorKind::UnderlyingBackendError) .chain_err(|| ErrorKind::UnderlyingBackendError)
@ -108,7 +108,7 @@ where
} }
fn get_framebuffer_dimensions(&self) -> (u32, u32) { fn get_framebuffer_dimensions(&self) -> (u32, u32) {
let (w, h) = self.pending_mode().size(); let (w, h) = self.pending_mode().map(|mode| mode.size()).unwrap_or((1, 1));
(w as u32, h as u32) (w as u32, h as u32)
} }

View File

@ -45,28 +45,8 @@ impl<D: RawDevice + 'static> Backend for Gbm<D> {
} }
} }
/// Arguments necessary to construct a `GbmSurface`
pub struct SurfaceArguments {
/// Crtc
pub crtc: crtc::Handle,
/// Mode
pub mode: Mode,
/// Connectors
pub connectors: Vec<connector::Handle>,
}
impl From<(crtc::Handle, Mode, Vec<connector::Handle>)> for SurfaceArguments {
fn from((crtc, mode, connectors): (crtc::Handle, Mode, Vec<connector::Handle>)) -> Self {
SurfaceArguments {
crtc,
mode,
connectors: Vec::from_iter(connectors),
}
}
}
unsafe impl<D: RawDevice + ControlDevice + 'static> NativeDisplay<Gbm<D>> for GbmDevice<D> { unsafe impl<D: RawDevice + ControlDevice + 'static> NativeDisplay<Gbm<D>> for GbmDevice<D> {
type Arguments = SurfaceArguments; type Arguments = crtc::Handle;
type Error = Error; type Error = Error;
fn is_backend(&self) -> bool { fn is_backend(&self) -> bool {
@ -77,8 +57,8 @@ unsafe impl<D: RawDevice + ControlDevice + 'static> NativeDisplay<Gbm<D>> for Gb
Ok(self.dev.borrow().as_raw() as *const _) Ok(self.dev.borrow().as_raw() as *const _)
} }
fn create_surface(&mut self, args: SurfaceArguments) -> Result<GbmSurface<D>> { fn create_surface(&mut self, crtc: crtc::Handle) -> Result<GbmSurface<D>> {
Device::create_surface(self, args.crtc, args.mode, args.connectors) Device::create_surface(self, crtc)
} }
} }

View File

@ -16,6 +16,12 @@ error_chain! {
display("Creation of gbm surface failed"), display("Creation of gbm surface failed"),
} }
#[doc = "No mode is set, blocking the current operation"]
NoModeSet {
description("No mode is currently set"),
display("No mode is currently set"),
}
#[doc = "Creation of gbm buffer object failed"] #[doc = "Creation of gbm buffer object failed"]
BufferCreationFailed { BufferCreationFailed {
description("Creation of gbm buffer object failed"), description("Creation of gbm buffer object failed"),

View File

@ -119,18 +119,16 @@ impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D> {
self.dev.borrow_mut().clear_handler(); self.dev.borrow_mut().clear_handler();
} }
fn create_surface( fn create_surface(&mut self, crtc: crtc::Handle) -> Result<GbmSurface<D>> {
&mut self,
crtc: crtc::Handle,
mode: Mode,
connectors: impl IntoIterator<Item = connector::Handle>,
) -> Result<GbmSurface<D>> {
info!(self.logger, "Initializing GbmSurface"); info!(self.logger, "Initializing GbmSurface");
let drm_surface = Device::create_surface(&mut **self.dev.borrow_mut(), crtc, mode, connectors) let drm_surface = Device::create_surface(&mut **self.dev.borrow_mut(), crtc)
.chain_err(|| ErrorKind::UnderlyingBackendError)?; .chain_err(|| ErrorKind::UnderlyingBackendError)?;
let (w, h) = mode.size(); let (w, h) = drm_surface
.pending_mode()
.map(|mode| mode.size())
.unwrap_or((1, 1));
let surface = self let surface = self
.dev .dev
.borrow() .borrow()

View File

@ -90,7 +90,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
} }
pub fn recreate(&self) -> Result<()> { pub fn recreate(&self) -> Result<()> {
let (w, h) = self.pending_mode().size(); let (w, h) = self.pending_mode().chain_err(|| ErrorKind::NoModeSet)?.size();
// Recreate the surface and the related resources to match the new // Recreate the surface and the related resources to match the new
// resolution. // resolution.
@ -161,15 +161,15 @@ impl<D: RawDevice + 'static> Surface for GbmSurfaceInternal<D> {
.chain_err(|| ErrorKind::UnderlyingBackendError) .chain_err(|| ErrorKind::UnderlyingBackendError)
} }
fn current_mode(&self) -> Mode { fn current_mode(&self) -> Option<Mode> {
self.crtc.current_mode() self.crtc.current_mode()
} }
fn pending_mode(&self) -> Mode { fn pending_mode(&self) -> Option<Mode> {
self.crtc.pending_mode() self.crtc.pending_mode()
} }
fn use_mode(&self, mode: Mode) -> Result<()> { fn use_mode(&self, mode: Option<Mode>) -> Result<()> {
self.crtc self.crtc
.use_mode(mode) .use_mode(mode)
.chain_err(|| ErrorKind::UnderlyingBackendError) .chain_err(|| ErrorKind::UnderlyingBackendError)
@ -314,15 +314,15 @@ impl<D: RawDevice + 'static> Surface for GbmSurface<D> {
self.0.remove_connector(connector) self.0.remove_connector(connector)
} }
fn current_mode(&self) -> Mode { fn current_mode(&self) -> Option<Mode> {
self.0.current_mode() self.0.current_mode()
} }
fn pending_mode(&self) -> Mode { fn pending_mode(&self) -> Option<Mode> {
self.0.pending_mode() self.0.pending_mode()
} }
fn use_mode(&self, mode: Mode) -> Result<()> { fn use_mode(&self, mode: Option<Mode>) -> Result<()> {
self.0.use_mode(mode) self.0.use_mode(mode)
} }
} }

View File

@ -46,7 +46,7 @@ impl<A: AsRawFd + 'static> AsRawFd for Dev<A> {
} }
impl<A: AsRawFd + 'static> BasicDevice for Dev<A> {} impl<A: AsRawFd + 'static> BasicDevice for Dev<A> {}
impl<A: AsRawFd + 'static> ControlDevice for Dev<A> {} impl<A: AsRawFd + 'static> ControlDevice for Dev<A> {}
impl<A: AsRawFd + 'static> Drop for Dev<A> { impl<A: AsRawFd + 'static> Drop for Dev<A> {
fn drop(&mut self) { fn drop(&mut self) {
info!(self.logger, "Dropping device: {:?}", self.dev_path()); info!(self.logger, "Dropping device: {:?}", self.dev_path());
if self.active.load(Ordering::SeqCst) { if self.active.load(Ordering::SeqCst) {
@ -163,12 +163,7 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
let _ = self.handler.take(); let _ = self.handler.take();
} }
fn create_surface( fn create_surface(&mut self, crtc: crtc::Handle) -> Result<LegacyDrmSurface<A>> {
&mut self,
crtc: crtc::Handle,
mode: Mode,
connectors: impl IntoIterator<Item = connector::Handle>,
) -> Result<LegacyDrmSurface<A>> {
if self.backends.borrow().contains_key(&crtc) { if self.backends.borrow().contains_key(&crtc) {
bail!(ErrorKind::CrtcAlreadyInUse(crtc)); bail!(ErrorKind::CrtcAlreadyInUse(crtc));
} }
@ -177,52 +172,38 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
bail!(ErrorKind::DeviceInactive); bail!(ErrorKind::DeviceInactive);
} }
let connectors = HashSet::from_iter(connectors); let crtc_info = crtc::Info::load_from_device(self, crtc)
// check if we have an encoder for every connector and the mode mode .chain_err(|| ErrorKind::DrmDev(format!("Error loading crtc info on {:?}", self.dev_path())))?;
for connector in &connectors {
let con_info = connector::Info::load_from_device(self, *connector).chain_err(|| { let mode = crtc_info.mode();
let mut connectors = HashSet::new();
let res_handles = ControlDevice::resource_handles(self).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(|| {
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() {
// check the mode let enc_info = encoder::Info::load_from_device(self, enc).chain_err(|| {
if !con_info.modes().contains(&mode) { ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", self.dev_path()))
bail!(ErrorKind::ModeNotSuitable(mode)); })?;
} if let Some(current_crtc) = enc_info.current_crtc() {
if crtc == current_crtc {
// check for every connector which encoders it does support connectors.insert(con);
let encoders = con_info }
.encoders() }
.iter()
.map(|encoder| {
encoder::Info::load_from_device(self, *encoder).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 = ControlDevice::resource_handles(self).chain_err(|| {
ErrorKind::DrmDev(format!("Error loading drm resources on {:?}", self.dev_path()))
})?;
if !encoders
.iter()
.map(|encoder| encoder.possible_crtcs())
.any(|crtc_list| resource_handles.filter_crtcs(crtc_list).contains(&crtc))
{
bail!(ErrorKind::NoSuitableEncoder(con_info, crtc))
} }
} }
// configuration is valid, the kernel will figure out the rest
let logger = self.logger.new(o!("crtc" => format!("{:?}", crtc)));
let state = State { mode, connectors }; let state = State { mode, connectors };
let backend = Rc::new(LegacyDrmSurfaceInternal { let backend = Rc::new(LegacyDrmSurfaceInternal {
dev: self.dev.clone(), dev: self.dev.clone(),
crtc, crtc,
state: RwLock::new(state.clone()), state: RwLock::new(state.clone()),
pending: RwLock::new(state), pending: RwLock::new(state),
logger, logger: self.logger.new(o!("crtc" => format!("{:?}", crtc))),
}); });
self.backends.borrow_mut().insert(crtc, Rc::downgrade(&backend)); self.backends.borrow_mut().insert(crtc, Rc::downgrade(&backend));

View File

@ -15,7 +15,7 @@ use super::{error::*, Dev};
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct State { pub struct State {
pub mode: Mode, pub mode: Option<Mode>,
pub connectors: HashSet<connector::Handle>, pub connectors: HashSet<connector::Handle>,
} }
@ -77,11 +77,11 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurfaceInternal<A> {
self.pending.read().unwrap().connectors.clone() self.pending.read().unwrap().connectors.clone()
} }
fn current_mode(&self) -> Mode { fn current_mode(&self) -> Option<Mode> {
self.state.read().unwrap().mode.clone() self.state.read().unwrap().mode.clone()
} }
fn pending_mode(&self) -> Mode { fn pending_mode(&self) -> Option<Mode> {
self.pending.read().unwrap().mode.clone() self.pending.read().unwrap().mode.clone()
} }
@ -93,7 +93,7 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurfaceInternal<A> {
let mut pending = self.pending.write().unwrap(); let mut pending = self.pending.write().unwrap();
// check if the connector can handle the current mode // check if the connector can handle the current mode
if info.modes().contains(&pending.mode) { if info.modes().contains(pending.mode.as_ref().unwrap()) {
// check if there is a valid encoder // check if there is a valid encoder
let encoders = info let encoders = info
.encoders() .encoders()
@ -119,7 +119,7 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurfaceInternal<A> {
pending.connectors.insert(connector); pending.connectors.insert(connector);
Ok(()) Ok(())
} else { } else {
bail!(ErrorKind::ModeNotSuitable(pending.mode)); bail!(ErrorKind::ModeNotSuitable(pending.mode.unwrap()));
} }
} }
@ -128,18 +128,20 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurfaceInternal<A> {
Ok(()) Ok(())
} }
fn use_mode(&self, mode: Mode) -> Result<()> { fn use_mode(&self, mode: Option<Mode>) -> Result<()> {
let mut pending = self.pending.write().unwrap(); let mut pending = self.pending.write().unwrap();
// check the connectors // check the connectors
for connector in &pending.connectors { if let Some(mode) = mode {
if !connector::Info::load_from_device(self, *connector) for connector in &pending.connectors {
.chain_err(|| { if !connector::Info::load_from_device(self, *connector)
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path())) .chain_err(|| {
})?.modes() ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path()))
.contains(&mode) })?.modes()
{ .contains(&mode)
bail!(ErrorKind::ModeNotSuitable(mode)); {
bail!(ErrorKind::ModeNotSuitable(mode));
}
} }
} }
@ -179,7 +181,11 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
} }
if current.mode != pending.mode { if current.mode != pending.mode {
info!(self.logger, "Setting new mode: {:?}", pending.mode.name()); info!(
self.logger,
"Setting new mode: {:?}",
pending.mode.as_ref().unwrap().name()
);
} }
} }
@ -194,7 +200,7 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
.map(|x| *x) .map(|x| *x)
.collect::<Vec<connector::Handle>>(), .collect::<Vec<connector::Handle>>(),
(0, 0), (0, 0),
Some(pending.mode), pending.mode,
).chain_err(|| { ).chain_err(|| {
ErrorKind::DrmDev(format!( ErrorKind::DrmDev(format!(
"Error setting crtc {:?} on {:?}", "Error setting crtc {:?} on {:?}",
@ -270,11 +276,11 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurface<A> {
self.0.pending_connectors() self.0.pending_connectors()
} }
fn current_mode(&self) -> Mode { fn current_mode(&self) -> Option<Mode> {
self.0.current_mode() self.0.current_mode()
} }
fn pending_mode(&self) -> Mode { fn pending_mode(&self) -> Option<Mode> {
self.0.pending_mode() self.0.pending_mode()
} }
@ -286,7 +292,7 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurface<A> {
self.0.remove_connector(connector) self.0.remove_connector(connector)
} }
fn use_mode(&self, mode: Mode) -> Result<()> { fn use_mode(&self, mode: Option<Mode>) -> Result<()> {
self.0.use_mode(mode) self.0.use_mode(mode)
} }
} }

View File

@ -38,8 +38,6 @@ pub trait Device: AsRawFd + DevPath {
fn create_surface( fn create_surface(
&mut self, &mut self,
ctrc: crtc::Handle, ctrc: crtc::Handle,
mode: Mode,
connectors: impl IntoIterator<Item = connector::Handle>,
) -> Result<Self::Surface, <Self::Surface as Surface>::Error>; ) -> Result<Self::Surface, <Self::Surface as Surface>::Error>;
fn process_events(&mut self); fn process_events(&mut self);
fn resource_info<T: ResourceInfo>( fn resource_info<T: ResourceInfo>(
@ -62,9 +60,9 @@ pub trait Surface {
fn pending_connectors(&self) -> Self::Connectors; fn pending_connectors(&self) -> Self::Connectors;
fn add_connector(&self, connector: connector::Handle) -> Result<(), Self::Error>; fn add_connector(&self, connector: connector::Handle) -> Result<(), Self::Error>;
fn remove_connector(&self, connector: connector::Handle) -> Result<(), Self::Error>; fn remove_connector(&self, connector: connector::Handle) -> Result<(), Self::Error>;
fn current_mode(&self) -> Mode; fn current_mode(&self) -> Option<Mode>;
fn pending_mode(&self) -> Mode; fn pending_mode(&self) -> Option<Mode>;
fn use_mode(&self, mode: Mode) -> Result<(), Self::Error>; fn use_mode(&self, mode: Option<Mode>) -> Result<(), Self::Error>;
} }
pub trait RawSurface: Surface + ControlDevice + BasicDevice { pub trait RawSurface: Surface + ControlDevice + BasicDevice {