drm: Remove associated Return type from Device

This commit is contained in:
Victor Brekenfeld 2018-11-22 10:04:19 +01:00
parent f8499e533a
commit f17e37465b
9 changed files with 262 additions and 203 deletions

View File

@ -1,8 +1,8 @@
use drm::control::{crtc, Mode};
use std::cell::RefCell;
use std::collections::HashMap;
use std::iter::FromIterator;
use std::os::unix::io::{AsRawFd, RawFd};
use std::rc::{Rc, Weak};
use std::rc::Rc;
use wayland_server::Display;
use super::{Device, DeviceHandler, Surface};
@ -28,7 +28,6 @@ pub struct EglDevice<
<D as Device>::Surface: NativeSurface,
{
dev: Rc<RefCell<EGLContext<B, D>>>,
backends: Rc<RefCell<HashMap<crtc::Handle, Weak<EglSurface<B, D>>>>>,
logger: ::slog::Logger,
}
@ -85,7 +84,6 @@ where
dev: Rc::new(RefCell::new(
EGLContext::new(dev, attributes, Default::default(), log.clone()).map_err(Error::from)?,
)),
backends: Rc::new(RefCell::new(HashMap::new())),
logger: log,
})
}
@ -98,36 +96,18 @@ struct InternalDeviceHandler<
<D as Device>::Surface: NativeSurface,
{
handler: Box<DeviceHandler<Device = EglDevice<B, D>> + 'static>,
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<EglSurface<B, D>>>>>,
logger: ::slog::Logger,
}
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
DeviceHandler for InternalDeviceHandler<B, D>
where
<D as NativeDisplay<B>>::Arguments: From<(
crtc::Handle,
Mode,
<<D as Device>::Surface as Surface>::Connectors,
)>,
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface,
{
type Device = D;
fn vblank(&mut self, surface: &<D as Device>::Surface) {
if let Some(backends) = self.backends.upgrade() {
if let Some(surface) = backends.borrow().get(&surface.crtc()) {
if let Some(surface) = surface.upgrade() {
self.handler.vblank(&*surface);
}
} else {
warn!(
self.logger,
"Surface ({:?}) not managed by egl, event not handled.",
surface.crtc()
);
}
}
fn vblank(&mut self, crtc: crtc::Handle) {
self.handler.vblank(crtc)
}
fn error(&mut self, error: <<D as Device>::Surface as Surface>::Error) {
self.handler
@ -138,21 +118,14 @@ where
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> Device
for EglDevice<B, D>
where
<D as NativeDisplay<B>>::Arguments: From<(
crtc::Handle,
Mode,
<<D as Device>::Surface as Surface>::Connectors,
)>,
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, Vec<connector::Handle>)>,
<D as Device>::Surface: NativeSurface,
{
type Surface = EglSurface<B, D>;
type Return = Rc<EglSurface<B, D>>;
fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static) {
self.dev.borrow_mut().set_handler(InternalDeviceHandler {
handler: Box::new(handler),
backends: Rc::downgrade(&self.backends),
logger: self.logger.clone(),
});
}
@ -164,21 +137,19 @@ where
&mut self,
crtc: crtc::Handle,
mode: Mode,
connectors: impl Into<<<Self as Device>::Surface as Surface>::Connectors>,
) -> Result<Rc<EglSurface<B, D>>> {
connectors: impl IntoIterator<Item = connector::Handle>,
) -> Result<EglSurface<B, D>> {
info!(self.logger, "Initializing EglSurface");
let surface = self
.dev
.borrow_mut()
.create_surface((crtc, mode, connectors.into()).into())?;
.create_surface((crtc, mode, Vec::from_iter(connectors)).into())?;
let backend = Rc::new(EglSurface {
Ok(EglSurface {
dev: self.dev.clone(),
surface,
});
self.backends.borrow_mut().insert(crtc, Rc::downgrade(&backend));
Ok(backend)
})
}
fn process_events(&mut self) {

View File

@ -1,4 +1,4 @@
use backend::drm::{Device, RawDevice, RawSurface, Surface};
use backend::drm::{connector, Device, RawDevice, RawSurface, Surface};
use backend::egl::error::Result as EglResult;
use backend::egl::ffi;
use backend::egl::native::{Backend, NativeDisplay, NativeSurface};
@ -9,23 +9,17 @@ use super::{GbmDevice, GbmSurface};
use drm::control::{crtc, Device as ControlDevice, Mode};
use gbm::AsRaw;
use std::iter::{FromIterator, IntoIterator};
use std::marker::PhantomData;
use std::ptr;
use std::rc::Rc;
/// Gbm backend type
pub struct Gbm<D: RawDevice + 'static>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
pub struct Gbm<D: RawDevice + 'static> {
_userdata: PhantomData<D>,
}
impl<D: RawDevice + 'static> Backend for Gbm<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
type Surface = Rc<GbmSurface<D>>;
impl<D: RawDevice + 'static> Backend for Gbm<D> {
type Surface = GbmSurface<D>;
unsafe fn get_display<F>(
display: ffi::NativeDisplayType,
@ -52,37 +46,27 @@ where
}
/// Arguments necessary to construct a `GbmSurface`
pub struct SurfaceArguments<D: RawDevice + 'static>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
pub struct SurfaceArguments {
/// Crtc
pub crtc: crtc::Handle,
/// Mode
pub mode: Mode,
/// Connectors
pub connectors: <GbmSurface<D> as Surface>::Connectors,
pub connectors: Vec<connector::Handle>,
}
impl<D: RawDevice + 'static> From<(crtc::Handle, Mode, <GbmSurface<D> as Surface>::Connectors)>
for SurfaceArguments<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
fn from((crtc, mode, connectors): (crtc::Handle, Mode, <GbmSurface<D> as Surface>::Connectors)) -> Self {
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,
connectors: Vec::from_iter(connectors),
}
}
}
unsafe impl<D: RawDevice + ControlDevice + 'static> NativeDisplay<Gbm<D>> for GbmDevice<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
type Arguments = SurfaceArguments<D>;
unsafe impl<D: RawDevice + ControlDevice + 'static> NativeDisplay<Gbm<D>> for GbmDevice<D> {
type Arguments = SurfaceArguments;
type Error = Error;
fn is_backend(&self) -> bool {
@ -93,24 +77,21 @@ where
Ok(self.dev.borrow().as_raw() as *const _)
}
fn create_surface(&mut self, args: SurfaceArguments<D>) -> Result<Rc<GbmSurface<D>>> {
fn create_surface(&mut self, args: SurfaceArguments) -> Result<GbmSurface<D>> {
Device::create_surface(self, args.crtc, args.mode, args.connectors)
}
}
unsafe impl<D: RawDevice + 'static> NativeSurface for Rc<GbmSurface<D>>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
unsafe impl<D: RawDevice + 'static> NativeSurface for GbmSurface<D> {
fn ptr(&self) -> ffi::NativeWindowType {
self.surface.borrow().as_raw() as *const _
self.0.surface.borrow().as_raw() as *const _
}
fn swap_buffers<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
where
F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
{
if ::std::borrow::Borrow::borrow(&self.crtc).commit_pending() {
if self.0.crtc.commit_pending() {
self.recreate(flip).map_err(|_| SwapBuffersError::ContextLost)
} else {
self.page_flip(flip)

View File

@ -1,6 +1,6 @@
use super::{Device, DeviceHandler, RawDevice, Surface};
use drm::control::{crtc, framebuffer, Device as ControlDevice, Mode};
use drm::control::{connector, crtc, framebuffer, Device as ControlDevice, Mode};
use gbm::{self, BufferObjectFlags, Format as GbmFormat};
use std::cell::{Cell, RefCell};
@ -14,6 +14,7 @@ use self::error::*;
mod surface;
pub use self::surface::GbmSurface;
use self::surface::GbmSurfaceInternal;
pub mod egl;
@ -23,19 +24,13 @@ pub mod session;
static LOAD: Once = ONCE_INIT;
/// Representation of an open gbm device to create rendering backends
pub struct GbmDevice<D: RawDevice + ControlDevice + 'static>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
pub struct GbmDevice<D: RawDevice + ControlDevice + 'static> {
pub(self) dev: Rc<RefCell<gbm::Device<D>>>,
backends: Rc<RefCell<HashMap<crtc::Handle, Weak<GbmSurface<D>>>>>,
backends: Rc<RefCell<HashMap<crtc::Handle, Weak<GbmSurfaceInternal<D>>>>>,
logger: ::slog::Logger,
}
impl<D: RawDevice + ControlDevice + 'static> GbmDevice<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
impl<D: RawDevice + ControlDevice + 'static> GbmDevice<D> {
/// Create a new `GbmDevice` from an open drm node
///
/// Returns an error if the file is no valid drm node or context creation was not
@ -73,33 +68,26 @@ where
}
}
struct InternalDeviceHandler<D: RawDevice + ControlDevice + 'static>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
struct InternalDeviceHandler<D: RawDevice + ControlDevice + 'static> {
handler: Box<DeviceHandler<Device = GbmDevice<D>> + 'static>,
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<GbmSurface<D>>>>>,
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<GbmSurfaceInternal<D>>>>>,
logger: ::slog::Logger,
}
impl<D: RawDevice + ControlDevice + 'static> DeviceHandler for InternalDeviceHandler<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
impl<D: RawDevice + ControlDevice + 'static> DeviceHandler for InternalDeviceHandler<D> {
type Device = D;
fn vblank(&mut self, surface: &<D as Device>::Surface) {
fn vblank(&mut self, crtc: crtc::Handle) {
if let Some(backends) = self.backends.upgrade() {
if let Some(surface) = backends.borrow().get(&surface.crtc()) {
if let Some(surface) = backends.borrow().get(&crtc) {
if let Some(surface) = surface.upgrade() {
surface.unlock_buffer();
self.handler.vblank(&*surface);
self.handler.vblank(crtc);
}
} else {
warn!(
self.logger,
"Surface ({:?}) not managed by gbm, event not handled.",
surface.crtc()
"Surface ({:?}) not managed by gbm, event not handled.", crtc
);
}
}
@ -110,12 +98,8 @@ where
}
}
impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D> {
type Surface = GbmSurface<D>;
type Return = Rc<GbmSurface<D>>;
fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static) {
self.dev.borrow_mut().set_handler(InternalDeviceHandler {
@ -133,8 +117,8 @@ where
&mut self,
crtc: crtc::Handle,
mode: Mode,
connectors: impl Into<<Self::Surface as Surface>::Connectors>,
) -> Result<Rc<GbmSurface<D>>> {
connectors: impl IntoIterator<Item = connector::Handle>,
) -> Result<GbmSurface<D>> {
info!(self.logger, "Initializing GbmSurface");
let (w, h) = mode.size();
@ -173,7 +157,7 @@ where
(0, 0),
));
let backend = Rc::new(GbmSurface {
let backend = Rc::new(GbmSurfaceInternal {
dev: self.dev.clone(),
surface: RefCell::new(surface),
crtc: Device::create_surface(&mut **self.dev.borrow_mut(), crtc, mode, connectors)
@ -185,7 +169,7 @@ where
logger: self.logger.new(o!("crtc" => format!("{:?}", crtc))),
});
self.backends.borrow_mut().insert(crtc, Rc::downgrade(&backend));
Ok(backend)
Ok(GbmSurface(backend))
}
fn process_events(&mut self) {
@ -193,10 +177,7 @@ where
}
}
impl<D: RawDevice + ControlDevice + 'static> AsRawFd for GbmDevice<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
impl<D: RawDevice + ControlDevice + 'static> AsRawFd for GbmDevice<D> {
fn as_raw_fd(&self) -> RawFd {
self.dev.borrow().as_raw_fd()
}

View File

@ -5,26 +5,22 @@ use std::collections::HashMap;
use std::os::unix::io::RawFd;
use std::rc::{Rc, Weak};
use super::{GbmDevice, GbmSurface};
use backend::drm::{Device, RawDevice, RawSurface};
use super::{GbmDevice, GbmSurfaceInternal};
use backend::drm::{RawDevice, RawSurface};
use backend::session::{AsSessionObserver, SessionObserver};
/// `SessionObserver` linked to the `DrmDevice` it was created from.
pub struct GbmDeviceObserver<
S: SessionObserver + 'static,
D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static,
> where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
> {
observer: S,
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<GbmSurface<D>>>>>,
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<GbmSurfaceInternal<D>>>>>,
logger: ::slog::Logger,
}
impl<S: SessionObserver + 'static, D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static>
AsSessionObserver<GbmDeviceObserver<S, D>> for GbmDevice<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
fn observer(&mut self) -> GbmDeviceObserver<S, D> {
GbmDeviceObserver {
@ -37,8 +33,6 @@ where
impl<S: SessionObserver + 'static, D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static>
SessionObserver for GbmDeviceObserver<S, D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
fn pause(&mut self, devnum: Option<(u32, u32)>) {
self.observer.pause(devnum);
@ -51,7 +45,8 @@ where
for (crtc, backend) in backends.borrow().iter() {
if let Some(backend) = backend.upgrade() {
// restart rendering loop
if let Err(err) = ::std::borrow::Borrow::borrow(&backend.crtc)
if let Err(err) = &backend
.crtc
.page_flip(backend.current_frame_buffer.get().handle())
{
warn!(self.logger, "Failed to restart rendering loop. Error: {}", err);

View File

@ -1,7 +1,7 @@
use super::super::{Device, RawDevice, RawSurface, Surface};
use super::error::*;
use drm::control::{connector, crtc, framebuffer, Mode, ResourceInfo};
use drm::control::{connector, crtc, framebuffer, Mode, ResourceHandles, ResourceInfo};
use gbm::{self, BufferObject, BufferObjectFlags, Format as GbmFormat, SurfaceBufferHandle};
use image::{ImageBuffer, Rgba};
@ -9,17 +9,14 @@ use std::cell::{Cell, RefCell};
use std::os::unix::io::AsRawFd;
use std::rc::Rc;
use backend::drm::legacy::{LegacyDrmDevice, LegacyDrmSurface};
use backend::drm::legacy::LegacyDrmDevice;
use backend::graphics::CursorBackend;
use backend::graphics::SwapBuffersError;
pub struct GbmSurface<D: RawDevice + 'static>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
pub(super) struct GbmSurfaceInternal<D: RawDevice + 'static> {
pub(super) dev: Rc<RefCell<gbm::Device<D>>>,
pub(super) surface: RefCell<gbm::Surface<framebuffer::Info>>,
pub(super) crtc: <D as Device>::Return,
pub(super) crtc: <D as Device>::Surface,
pub(super) cursor: Cell<(BufferObject<()>, (u32, u32))>,
pub(super) current_frame_buffer: Cell<framebuffer::Info>,
pub(super) front_buffer: Cell<SurfaceBufferHandle<framebuffer::Info>>,
@ -27,10 +24,7 @@ where
pub(super) logger: ::slog::Logger,
}
impl<D: RawDevice + 'static> GbmSurface<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
pub(super) fn unlock_buffer(&self) {
// after the page swap is finished we need to release the rendered buffer.
// this is called from the PageFlipHandler
@ -79,15 +73,14 @@ where
let fb = if let Some(info) = maybe_fb {
info
} else {
let fb = framebuffer::create(::std::borrow::Borrow::borrow(&self.crtc), &*next_bo)
.map_err(|_| SwapBuffersError::ContextLost)?;
let fb = framebuffer::create(&self.crtc, &*next_bo).map_err(|_| SwapBuffersError::ContextLost)?;
next_bo.set_userdata(fb).unwrap();
fb
};
self.next_buffer.set(Some(next_bo));
trace!(self.logger, "Queueing Page flip");
::std::borrow::Borrow::borrow(&self.crtc).page_flip(fb.handle())?;
self.crtc.page_flip(fb.handle())?;
self.current_frame_buffer.set(fb);
@ -119,9 +112,7 @@ where
{
if let Some(mut old_bo) = self.next_buffer.take() {
if let Ok(Some(fb)) = old_bo.take_userdata() {
if let Err(err) =
framebuffer::destroy(::std::borrow::Borrow::borrow(&self.crtc), fb.handle())
{
if let Err(err) = framebuffer::destroy(&self.crtc, fb.handle()) {
warn!(
self.logger,
"Error releasing old back_buffer framebuffer: {:?}", err
@ -141,10 +132,10 @@ where
debug!(self.logger, "FrontBuffer color format: {:?}", front_bo.format());
// we also need a new framebuffer for the front buffer
let fb = framebuffer::create(::std::borrow::Borrow::borrow(&self.crtc), &*front_bo)
let fb = framebuffer::create(&self.crtc, &*front_bo)
.chain_err(|| ErrorKind::UnderlyingBackendError)?;
::std::borrow::Borrow::borrow(&self.crtc)
self.crtc
.commit(fb.handle())
.chain_err(|| ErrorKind::UnderlyingBackendError)?;
@ -152,7 +143,7 @@ where
front_bo
});
if let Ok(Some(fb)) = old_front_bo.take_userdata() {
if let Err(err) = framebuffer::destroy(::std::borrow::Borrow::borrow(&self.crtc), fb.handle()) {
if let Err(err) = framebuffer::destroy(&self.crtc, fb.handle()) {
warn!(
self.logger,
"Error releasing old front_buffer framebuffer: {:?}", err
@ -167,47 +158,44 @@ where
}
}
impl<D: RawDevice + 'static> Surface for GbmSurface<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
impl<D: RawDevice + 'static> Surface for GbmSurfaceInternal<D> {
type Connectors = <<D as Device>::Surface as Surface>::Connectors;
type Error = Error;
fn crtc(&self) -> crtc::Handle {
::std::borrow::Borrow::borrow(&self.crtc).crtc()
self.crtc.crtc()
}
fn current_connectors(&self) -> Self::Connectors {
::std::borrow::Borrow::borrow(&self.crtc).current_connectors()
self.crtc.current_connectors()
}
fn pending_connectors(&self) -> Self::Connectors {
::std::borrow::Borrow::borrow(&self.crtc).pending_connectors()
self.crtc.pending_connectors()
}
fn add_connector(&self, connector: connector::Handle) -> Result<()> {
::std::borrow::Borrow::borrow(&self.crtc)
self.crtc
.add_connector(connector)
.chain_err(|| ErrorKind::UnderlyingBackendError)
}
fn remove_connector(&self, connector: connector::Handle) -> Result<()> {
::std::borrow::Borrow::borrow(&self.crtc)
self.crtc
.remove_connector(connector)
.chain_err(|| ErrorKind::UnderlyingBackendError)
}
fn current_mode(&self) -> Mode {
::std::borrow::Borrow::borrow(&self.crtc).current_mode()
self.crtc.current_mode()
}
fn pending_mode(&self) -> Mode {
::std::borrow::Borrow::borrow(&self.crtc).pending_mode()
self.crtc.pending_mode()
}
fn use_mode(&self, mode: Mode) -> Result<()> {
::std::borrow::Borrow::borrow(&self.crtc)
self.crtc
.use_mode(mode)
.chain_err(|| ErrorKind::UnderlyingBackendError)
}
@ -218,9 +206,8 @@ where
// Option 1: When there is GAT support, impl `GraphicsBackend` for `LegacyDrmBackend`
// using a new generic `B: Buffer` and use this:
/*
impl<'a, D: RawDevice + 'static> CursorBackend<'a> for GbmSurface<D>
impl<'a, D: RawDevice + 'static> CursorBackend<'a> for GbmSurfaceInternal<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
<D as RawDevice>::Surface: CursorBackend<'a>,
<<D as RawDevice>::Surface as CursorBackend<'a>>::CursorFormat: Buffer,
<<D as RawDevice>::Surface as CursorBackend<'a>>::Error: ::std::error::Error + Send
@ -229,9 +216,8 @@ where
//
// Option 2: When equality checks in where clauses are supported, we could at least do this:
/*
impl<'a, D: RawDevice + 'static> GraphicsBackend<'a> for GbmSurface<D>
impl<'a, D: RawDevice + 'static> GraphicsBackend<'a> for GbmSurfaceInternal<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
<D as RawDevice>::Surface: CursorBackend<'a>,
<<D as RawDevice>::Surface as CursorBackend<'a>>::CursorFormat=&'a Buffer,
<<D as RawDevice>::Surface as CursorBackend<'a>>::Error: ::std::error::Error + Send
@ -239,15 +225,14 @@ where
*/
// But for now got to do this:
impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurface<LegacyDrmDevice<A>> {
impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurfaceInternal<LegacyDrmDevice<A>> {
type CursorFormat = &'a ImageBuffer<Rgba<u8>, Vec<u8>>;
type Error = Error;
fn set_cursor_position(&self, x: u32, y: u32) -> Result<()> {
ResultExt::chain_err(
::std::borrow::Borrow::<Rc<LegacyDrmSurface<A>>>::borrow(&self.crtc).set_cursor_position(x, y),
|| ErrorKind::UnderlyingBackendError,
)
ResultExt::chain_err(self.crtc.set_cursor_position(x, y), || {
ErrorKind::UnderlyingBackendError
})
}
fn set_cursor_representation<'b>(
@ -279,11 +264,9 @@ impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurface<LegacyDrmDevice<
trace!(self.logger, "Setting the new imported cursor");
ResultExt::chain_err(
::std::borrow::Borrow::<Rc<LegacyDrmSurface<A>>>::borrow(&self.crtc)
.set_cursor_representation(&cursor, hotspot),
|| ErrorKind::UnderlyingBackendError,
)?;
ResultExt::chain_err(self.crtc.set_cursor_representation(&cursor, hotspot), || {
ErrorKind::UnderlyingBackendError
})?;
// and store it
self.cursor.set((cursor, hotspot));
@ -291,10 +274,7 @@ impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurface<LegacyDrmDevice<
}
}
impl<D: RawDevice + 'static> Drop for GbmSurface<D>
where
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
{
impl<D: RawDevice + 'static> Drop for GbmSurfaceInternal<D> {
fn drop(&mut self) {
// Drop framebuffers attached to the userdata of the gbm surface buffers.
// (They don't implement drop, as they need the device)
@ -308,12 +288,87 @@ where
}
} {
// ignore failure at this point
let _ = framebuffer::destroy(::std::borrow::Borrow::borrow(&self.crtc), fb.handle());
let _ = framebuffer::destroy(&self.crtc, fb.handle());
}
if let Ok(Some(fb)) = self.front_buffer.get_mut().take_userdata() {
// ignore failure at this point
let _ = framebuffer::destroy(::std::borrow::Borrow::borrow(&self.crtc), fb.handle());
let _ = framebuffer::destroy(&self.crtc, fb.handle());
}
}
}
pub struct GbmSurface<D: RawDevice + 'static>(pub(super) Rc<GbmSurfaceInternal<D>>);
impl<D: RawDevice + 'static> GbmSurface<D> {
pub fn page_flip<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
where
F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
{
self.0.page_flip(flip)
}
pub fn recreate<F>(&self, flip: F) -> Result<()>
where
F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
{
self.0.recreate(flip)
}
}
impl<D: RawDevice + 'static> Surface for GbmSurface<D> {
type Connectors = <<D as Device>::Surface as Surface>::Connectors;
type Error = Error;
fn crtc(&self) -> crtc::Handle {
self.0.crtc()
}
fn current_connectors(&self) -> Self::Connectors {
self.0.current_connectors()
}
fn pending_connectors(&self) -> Self::Connectors {
self.0.pending_connectors()
}
fn add_connector(&self, connector: connector::Handle) -> Result<()> {
self.0.add_connector(connector)
}
fn remove_connector(&self, connector: connector::Handle) -> Result<()> {
self.0.remove_connector(connector)
}
fn current_mode(&self) -> Mode {
self.0.current_mode()
}
fn pending_mode(&self) -> Mode {
self.0.pending_mode()
}
fn use_mode(&self, mode: Mode) -> Result<()> {
self.0.use_mode(mode)
}
}
impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurface<LegacyDrmDevice<A>> {
type CursorFormat = &'a ImageBuffer<Rgba<u8>, Vec<u8>>;
type Error = Error;
fn set_cursor_position(&self, x: u32, y: u32) -> Result<()> {
self.0.set_cursor_position(x, y)
}
fn set_cursor_representation<'b>(
&'b self,
buffer: &ImageBuffer<Rgba<u8>, Vec<u8>>,
hotspot: (u32, u32),
) -> Result<()>
where
'a: 'b,
{
self.0.set_cursor_representation(buffer, hotspot)
}
}

View File

@ -7,6 +7,7 @@ use nix::sys::stat::fstat;
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::iter::FromIterator;
use std::os::unix::io::{AsRawFd, RawFd};
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};
@ -14,7 +15,7 @@ use std::sync::{Arc, RwLock};
mod surface;
pub use self::surface::LegacyDrmSurface;
use self::surface::State;
use self::surface::{LegacyDrmSurfaceInternal, State};
pub mod error;
use self::error::*;
@ -28,7 +29,7 @@ pub struct LegacyDrmDevice<A: AsRawFd + 'static> {
priviledged: bool,
active: Arc<AtomicBool>,
old_state: HashMap<crtc::Handle, (crtc::Info, Vec<connector::Handle>)>,
backends: Rc<RefCell<HashMap<crtc::Handle, Weak<LegacyDrmSurface<A>>>>>,
backends: Rc<RefCell<HashMap<crtc::Handle, Weak<LegacyDrmSurfaceInternal<A>>>>>,
handler: Option<RefCell<Box<DeviceHandler<Device = LegacyDrmDevice<A>>>>>,
logger: ::slog::Logger,
}
@ -120,7 +121,6 @@ impl<A: AsRawFd + 'static> ControlDevice for LegacyDrmDevice<A> {}
impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
type Surface = LegacyDrmSurface<A>;
type Return = Rc<LegacyDrmSurface<A>>;
fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static) {
self.handler = Some(RefCell::new(Box::new(handler)));
@ -134,8 +134,8 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
&mut self,
crtc: crtc::Handle,
mode: Mode,
connectors: impl Into<<Self::Surface as Surface>::Connectors>,
) -> Result<Rc<LegacyDrmSurface<A>>> {
connectors: impl IntoIterator<Item = connector::Handle>,
) -> Result<LegacyDrmSurface<A>> {
if self.backends.borrow().contains_key(&crtc) {
bail!(ErrorKind::CrtcAlreadyInUse(crtc));
}
@ -144,7 +144,7 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
bail!(ErrorKind::DeviceInactive);
}
let connectors: HashSet<_> = connectors.into();
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(|| {
@ -184,7 +184,7 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
let state = State { mode, connectors };
let backend = Rc::new(LegacyDrmSurface {
let backend = Rc::new(LegacyDrmSurfaceInternal {
dev: self.dev.clone(),
crtc,
state: RwLock::new(state.clone()),
@ -193,7 +193,7 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
});
self.backends.borrow_mut().insert(crtc, Rc::downgrade(&backend));
Ok(backend)
Ok(LegacyDrmSurface(backend))
}
fn process_events(&mut self) {
@ -201,17 +201,18 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
Ok(events) => for event in events {
if let crtc::Event::PageFlip(event) = event {
if self.active.load(Ordering::SeqCst) {
if let Some(backend) = self
if self
.backends
.borrow()
.get(&event.crtc)
.iter()
.flat_map(|x| x.upgrade())
.next()
.is_some()
{
trace!(self.logger, "Handling event for backend {:?}", event.crtc);
if let Some(handler) = self.handler.as_ref() {
handler.borrow_mut().vblank(&backend);
handler.borrow_mut().vblank(event.crtc);
}
} else {
self.backends.borrow_mut().remove(&event.crtc);

View File

@ -9,7 +9,7 @@ use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use super::{Dev, LegacyDrmDevice, LegacyDrmSurface};
use super::{Dev, LegacyDrmDevice, LegacyDrmSurfaceInternal};
use backend::session::{AsSessionObserver, SessionObserver};
/// `SessionObserver` linked to the `DrmDevice` it was created from.
@ -19,7 +19,7 @@ pub struct LegacyDrmDeviceObserver<A: AsRawFd + 'static> {
priviledged: bool,
active: Arc<AtomicBool>,
old_state: HashMap<crtc::Handle, (crtc::Info, Vec<connector::Handle>)>,
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<LegacyDrmSurface<A>>>>>,
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<LegacyDrmSurfaceInternal<A>>>>>,
logger: ::slog::Logger,
}

View File

@ -19,7 +19,7 @@ pub struct State {
pub connectors: HashSet<connector::Handle>,
}
pub struct LegacyDrmSurface<A: AsRawFd + 'static> {
pub(super) struct LegacyDrmSurfaceInternal<A: AsRawFd + 'static> {
pub(super) dev: Rc<Dev<A>>,
pub(super) crtc: crtc::Handle,
pub(super) state: RwLock<State>,
@ -27,16 +27,16 @@ pub struct LegacyDrmSurface<A: AsRawFd + 'static> {
pub(super) logger: ::slog::Logger,
}
impl<A: AsRawFd + 'static> AsRawFd for LegacyDrmSurface<A> {
impl<A: AsRawFd + 'static> AsRawFd for LegacyDrmSurfaceInternal<A> {
fn as_raw_fd(&self) -> RawFd {
self.dev.as_raw_fd()
}
}
impl<A: AsRawFd + 'static> BasicDevice for LegacyDrmSurface<A> {}
impl<A: AsRawFd + 'static> ControlDevice for LegacyDrmSurface<A> {}
impl<A: AsRawFd + 'static> BasicDevice for LegacyDrmSurfaceInternal<A> {}
impl<A: AsRawFd + 'static> ControlDevice for LegacyDrmSurfaceInternal<A> {}
impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for LegacyDrmSurface<A> {
impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for LegacyDrmSurfaceInternal<A> {
type CursorFormat = &'a Buffer;
type Error = Error;
@ -61,7 +61,7 @@ impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for LegacyDrmSurface<A> {
}
}
impl<A: AsRawFd + 'static> Surface for LegacyDrmSurface<A> {
impl<A: AsRawFd + 'static> Surface for LegacyDrmSurfaceInternal<A> {
type Error = Error;
type Connectors = HashSet<connector::Handle>;
@ -149,7 +149,7 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurface<A> {
}
}
impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurface<A> {
impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
fn commit_pending(&self) -> bool {
*self.pending.read().unwrap() != *self.state.read().unwrap()
}
@ -220,9 +220,87 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurface<A> {
}
}
impl<A: AsRawFd + 'static> Drop for LegacyDrmSurface<A> {
impl<A: AsRawFd + 'static> Drop for LegacyDrmSurfaceInternal<A> {
fn drop(&mut self) {
// ignore failure at this point
let _ = crtc::clear_cursor(self, self.crtc);
}
}
pub struct LegacyDrmSurface<A: AsRawFd + 'static>(pub(super) Rc<LegacyDrmSurfaceInternal<A>>);
impl<A: AsRawFd + 'static> AsRawFd for LegacyDrmSurface<A> {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
impl<A: AsRawFd + 'static> BasicDevice for LegacyDrmSurface<A> {}
impl<A: AsRawFd + 'static> ControlDevice for LegacyDrmSurface<A> {}
impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for LegacyDrmSurface<A> {
type CursorFormat = &'a Buffer;
type Error = Error;
fn set_cursor_position(&self, x: u32, y: u32) -> Result<()> {
self.0.set_cursor_position(x, y)
}
fn set_cursor_representation<'b>(&'b self, buffer: Self::CursorFormat, hotspot: (u32, u32)) -> Result<()>
where
'a: 'b,
{
self.0.set_cursor_representation(buffer, hotspot)
}
}
impl<A: AsRawFd + 'static> Surface for LegacyDrmSurface<A> {
type Error = Error;
type Connectors = HashSet<connector::Handle>;
fn crtc(&self) -> crtc::Handle {
self.0.crtc()
}
fn current_connectors(&self) -> Self::Connectors {
self.0.current_connectors()
}
fn pending_connectors(&self) -> Self::Connectors {
self.0.pending_connectors()
}
fn current_mode(&self) -> Mode {
self.0.current_mode()
}
fn pending_mode(&self) -> Mode {
self.0.pending_mode()
}
fn add_connector(&self, connector: connector::Handle) -> Result<()> {
self.0.add_connector(connector)
}
fn remove_connector(&self, connector: connector::Handle) -> Result<()> {
self.0.remove_connector(connector)
}
fn use_mode(&self, mode: Mode) -> Result<()> {
self.0.use_mode(mode)
}
}
impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurface<A> {
fn commit_pending(&self) -> bool {
self.0.commit_pending()
}
fn commit(&self, framebuffer: framebuffer::Handle) -> Result<()> {
self.0.commit(framebuffer)
}
fn page_flip(&self, framebuffer: framebuffer::Handle) -> ::std::result::Result<(), SwapBuffersError> {
self.0.page_flip(framebuffer)
}
}

View File

@ -7,6 +7,7 @@ use drm::Device as BasicDevice;
use std::borrow::Borrow;
use std::error::Error;
use std::iter::IntoIterator;
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;
@ -26,13 +27,12 @@ pub mod legacy;
pub trait DeviceHandler {
type Device: Device + ?Sized;
fn vblank(&mut self, surface: &<<Self as DeviceHandler>::Device as Device>::Surface);
fn vblank(&mut self, crtc: crtc::Handle);
fn error(&mut self, error: <<<Self as DeviceHandler>::Device as Device>::Surface as Surface>::Error);
}
pub trait Device: AsRawFd + DevPath {
type Surface: Surface;
type Return: Borrow<Self::Surface>;
fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static);
fn clear_handler(&mut self);
@ -40,15 +40,12 @@ pub trait Device: AsRawFd + DevPath {
&mut self,
ctrc: crtc::Handle,
mode: Mode,
connectors: impl Into<<Self::Surface as Surface>::Connectors>,
) -> Result<Self::Return, <Self::Surface as Surface>::Error>;
connectors: impl IntoIterator<Item = connector::Handle>,
) -> Result<Self::Surface, <Self::Surface as Surface>::Error>;
fn process_events(&mut self);
}
pub trait RawDevice: Device<Surface = <Self as RawDevice>::Surface>
where
<Self as Device>::Return: Borrow<<Self as RawDevice>::Surface>,
{
pub trait RawDevice: Device<Surface = <Self as RawDevice>::Surface> {
type Surface: RawSurface;
}