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},
crtc,
encoder::Info as EncoderInfo,
ResourceInfo,
},
image::{ImageBuffer, Rgba},
input::Libinput,
@ -283,11 +282,9 @@ impl<S: SessionNotifier, Data: 'static> UdevHandlerImpl<S, Data> {
for encoder_info in encoder_infos {
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
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(
device
.create_surface(crtc, mode, vec![connector_info.handle()].into_iter())
.create_surface(crtc)
.unwrap(),
egl_display.clone(),
logger.clone(),
@ -332,11 +329,9 @@ impl<S: SessionNotifier, Data: 'static> UdevHandlerImpl<S, Data> {
for encoder_info in encoder_infos {
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
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(
device
.create_surface(crtc, mode, vec![connector_info.handle()].into_iter())
.create_surface(crtc)
.unwrap(),
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 std::iter::FromIterator;
use std::os::unix::io::{AsRawFd, RawFd};
use std::rc::Rc;
use wayland_server::Display;
@ -25,19 +24,19 @@ pub mod session;
/// Representation of an open gbm device to create rendering backends
pub struct EglDevice<
B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface,
{
dev: Rc<EGLContext<B, D>>,
logger: ::slog::Logger,
}
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> AsRawFd
for EglDevice<B, D>
impl<
B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> AsRawFd for EglDevice<B, D>
where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface,
{
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>
EglDevice<B, D>
impl<
B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> EglDevice<B, D>
where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface,
{
/// Create a new `EglGbmDrmDevice` from an open drm node
@ -96,18 +96,18 @@ where
struct InternalDeviceHandler<
B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface,
{
handler: Box<DeviceHandler<Device = EglDevice<B, D>> + 'static>,
}
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
DeviceHandler for InternalDeviceHandler<B, D>
impl<
B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> DeviceHandler for InternalDeviceHandler<B, D>
where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface,
{
type Device = D;
@ -121,10 +121,11 @@ where
}
}
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> Device
for EglDevice<B, D>
impl<
B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> Device for EglDevice<B, D>
where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface,
{
type Surface = EglSurface<B, D>;
@ -143,17 +144,10 @@ where
self.dev.borrow_mut().clear_handler()
}
fn create_surface(
&mut self,
crtc: crtc::Handle,
mode: Mode,
connectors: impl IntoIterator<Item = connector::Handle>,
) -> Result<EglSurface<B, D>> {
fn create_surface(&mut self, crtc: crtc::Handle) -> Result<EglSurface<B, D>> {
info!(self.logger, "Initializing EglSurface");
let surface = self
.dev
.create_surface((crtc, mode, Vec::from_iter(connectors)).into())?;
let surface = self.dev.create_surface(crtc)?;
Ok(EglSurface {
dev: self.dev.clone(),
@ -181,10 +175,11 @@ where
}
#[cfg(feature = "native_lib")]
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
EGLGraphicsBackend for EglDevice<B, D>
impl<
B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> EGLGraphicsBackend for EglDevice<B, D>
where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface,
{
fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> {
@ -192,13 +187,14 @@ where
}
}
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
Drop for EglDevice<B, D>
impl<
B: Backend<Surface = <D as Device>::Surface> + 'static,
D: Device + NativeDisplay<B, Arguments = crtc::Handle> + 'static,
> Drop for EglDevice<B, D>
where
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface,
{
fn drop(&mut self) {
self.clear_handler();
}
}
}

View File

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

View File

@ -54,15 +54,15 @@ where
.chain_err(|| ErrorKind::UnderlyingBackendError)
}
fn current_mode(&self) -> Mode {
fn current_mode(&self) -> Option<Mode> {
self.surface.current_mode()
}
fn pending_mode(&self) -> Mode {
fn pending_mode(&self) -> Option<Mode> {
self.surface.pending_mode()
}
fn use_mode(&self, mode: Mode) -> Result<()> {
fn use_mode(&self, mode: Option<Mode>) -> Result<()> {
self.surface
.use_mode(mode)
.chain_err(|| ErrorKind::UnderlyingBackendError)
@ -108,7 +108,7 @@ where
}
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)
}

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> {
type Arguments = SurfaceArguments;
type Arguments = crtc::Handle;
type Error = Error;
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 _)
}
fn create_surface(&mut self, args: SurfaceArguments) -> Result<GbmSurface<D>> {
Device::create_surface(self, args.crtc, args.mode, args.connectors)
fn create_surface(&mut self, crtc: crtc::Handle) -> Result<GbmSurface<D>> {
Device::create_surface(self, crtc)
}
}

View File

@ -16,6 +16,12 @@ error_chain! {
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"]
BufferCreationFailed {
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();
}
fn create_surface(
&mut self,
crtc: crtc::Handle,
mode: Mode,
connectors: impl IntoIterator<Item = connector::Handle>,
) -> Result<GbmSurface<D>> {
fn create_surface(&mut self, crtc: crtc::Handle) -> Result<GbmSurface<D>> {
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)?;
let (w, h) = mode.size();
let (w, h) = drm_surface
.pending_mode()
.map(|mode| mode.size())
.unwrap_or((1, 1));
let surface = self
.dev
.borrow()
@ -197,4 +195,4 @@ impl<D: RawDevice + ControlDevice + 'static> Drop for GbmDevice<D> {
fn drop(&mut self) {
self.clear_handler();
}
}
}

View File

@ -90,7 +90,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
}
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
// resolution.
@ -161,15 +161,15 @@ impl<D: RawDevice + 'static> Surface for GbmSurfaceInternal<D> {
.chain_err(|| ErrorKind::UnderlyingBackendError)
}
fn current_mode(&self) -> Mode {
fn current_mode(&self) -> Option<Mode> {
self.crtc.current_mode()
}
fn pending_mode(&self) -> Mode {
fn pending_mode(&self) -> Option<Mode> {
self.crtc.pending_mode()
}
fn use_mode(&self, mode: Mode) -> Result<()> {
fn use_mode(&self, mode: Option<Mode>) -> Result<()> {
self.crtc
.use_mode(mode)
.chain_err(|| ErrorKind::UnderlyingBackendError)
@ -314,15 +314,15 @@ impl<D: RawDevice + 'static> Surface for GbmSurface<D> {
self.0.remove_connector(connector)
}
fn current_mode(&self) -> Mode {
fn current_mode(&self) -> Option<Mode> {
self.0.current_mode()
}
fn pending_mode(&self) -> Mode {
fn pending_mode(&self) -> Option<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)
}
}

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

View File

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

View File

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