cargo fmt
This commit is contained in:
parent
bd5690bd77
commit
9ee44672a0
|
@ -1,15 +1,15 @@
|
||||||
use drm::control::{crtc, Mode};
|
use drm::control::{crtc, Mode};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::{Rc, Weak};
|
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
|
use std::rc::{Rc, Weak};
|
||||||
use wayland_server::Display;
|
use wayland_server::Display;
|
||||||
|
|
||||||
use backend::egl::{EGLContext, EGLGraphicsBackend, EGLDisplay};
|
use super::{Device, DeviceHandler, Surface};
|
||||||
use backend::egl::context::GlAttributes;
|
use backend::egl::context::GlAttributes;
|
||||||
use backend::egl::native::{Backend, NativeDisplay, NativeSurface};
|
|
||||||
use backend::egl::error::Result as EGLResult;
|
use backend::egl::error::Result as EGLResult;
|
||||||
use super::{Device, Surface, DeviceHandler};
|
use backend::egl::native::{Backend, NativeDisplay, NativeSurface};
|
||||||
|
use backend::egl::{EGLContext, EGLDisplay, EGLGraphicsBackend};
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
use self::error::*;
|
use self::error::*;
|
||||||
|
@ -21,24 +21,31 @@ pub use self::surface::*;
|
||||||
pub mod session;
|
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<B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
|
pub struct EglDevice<
|
||||||
where <D as Device>::Surface: NativeSurface
|
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||||
|
D: Device + NativeDisplay<B> + 'static,
|
||||||
|
> where
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
dev: Rc<RefCell<EGLContext<B, D>>>,
|
dev: Rc<RefCell<EGLContext<B, D>>>,
|
||||||
backends: Rc<RefCell<HashMap<crtc::Handle, Weak<EglSurface<B, D>>>>>,
|
backends: Rc<RefCell<HashMap<crtc::Handle, Weak<EglSurface<B, D>>>>>,
|
||||||
logger: ::slog::Logger,
|
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> + 'static> AsRawFd
|
||||||
where <D as Device>::Surface: NativeSurface
|
for EglDevice<B, D>
|
||||||
|
where
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
self.dev.borrow().as_raw_fd()
|
self.dev.borrow().as_raw_fd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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> + 'static>
|
||||||
where <D as Device>::Surface: NativeSurface
|
EglDevice<B, D>
|
||||||
|
where
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
/// Create a new `EglGbmDrmDevice` from an open drm node
|
/// Create a new `EglGbmDrmDevice` from an open drm node
|
||||||
///
|
///
|
||||||
|
@ -75,12 +82,8 @@ impl<B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDis
|
||||||
debug!(log, "Creating egl context from device");
|
debug!(log, "Creating egl context from device");
|
||||||
Ok(EglDevice {
|
Ok(EglDevice {
|
||||||
// Open the gbm device from the drm device and create a context based on that
|
// Open the gbm device from the drm device and create a context based on that
|
||||||
dev: Rc::new(RefCell::new(EGLContext::new(
|
dev: Rc::new(RefCell::new(
|
||||||
dev,
|
EGLContext::new(dev, attributes, Default::default(), log.clone()).map_err(Error::from)?,
|
||||||
attributes,
|
|
||||||
Default::default(),
|
|
||||||
log.clone(),
|
|
||||||
).map_err(Error::from)?
|
|
||||||
)),
|
)),
|
||||||
backends: Rc::new(RefCell::new(HashMap::new())),
|
backends: Rc::new(RefCell::new(HashMap::new())),
|
||||||
logger: log,
|
logger: log,
|
||||||
|
@ -88,20 +91,28 @@ impl<B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDis
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InternalDeviceHandler<B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
|
struct InternalDeviceHandler<
|
||||||
where <D as Device>::Surface: NativeSurface
|
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||||
|
D: Device + NativeDisplay<B> + 'static,
|
||||||
|
> where
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
handler: Box<DeviceHandler<Device=EglDevice<B, D>> + 'static>,
|
handler: Box<DeviceHandler<Device = EglDevice<B, D>> + 'static>,
|
||||||
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<EglSurface<B, D>>>>>,
|
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<EglSurface<B, D>>>>>,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
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> + 'static>
|
||||||
where
|
DeviceHandler for InternalDeviceHandler<B, D>
|
||||||
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, <<D as Device>::Surface as Surface>::Connectors)>,
|
where
|
||||||
<D as Device>::Surface: NativeSurface,
|
<D as NativeDisplay<B>>::Arguments: From<(
|
||||||
|
crtc::Handle,
|
||||||
|
Mode,
|
||||||
|
<<D as Device>::Surface as Surface>::Connectors,
|
||||||
|
)>,
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
type Device=D;
|
type Device = D;
|
||||||
|
|
||||||
fn vblank(&mut self, surface: &<D as Device>::Surface) {
|
fn vblank(&mut self, surface: &<D as Device>::Surface) {
|
||||||
if let Some(backends) = self.backends.upgrade() {
|
if let Some(backends) = self.backends.upgrade() {
|
||||||
|
@ -110,31 +121,41 @@ impl<B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDis
|
||||||
self.handler.vblank(&*surface);
|
self.handler.vblank(&*surface);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn!(self.logger, "Surface ({:?}) not managed by egl, event not handled.", surface.crtc());
|
warn!(
|
||||||
|
self.logger,
|
||||||
|
"Surface ({:?}) not managed by egl, event not handled.",
|
||||||
|
surface.crtc()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn error(&mut self, error: <<D as Device>::Surface as Surface>::Error) {
|
fn error(&mut self, error: <<D as Device>::Surface as Surface>::Error) {
|
||||||
self.handler.error(ResultExt::<()>::chain_err(Err(error), || ErrorKind::UnderlyingBackendError).unwrap_err())
|
self.handler
|
||||||
|
.error(ResultExt::<()>::chain_err(Err(error), || ErrorKind::UnderlyingBackendError).unwrap_err())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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> + 'static> Device
|
||||||
where
|
for EglDevice<B, D>
|
||||||
<D as NativeDisplay<B>>::Arguments: From<(crtc::Handle, Mode, <<D as Device>::Surface as Surface>::Connectors)>,
|
where
|
||||||
<D as Device>::Surface: NativeSurface,
|
<D as NativeDisplay<B>>::Arguments: From<(
|
||||||
|
crtc::Handle,
|
||||||
|
Mode,
|
||||||
|
<<D as Device>::Surface as Surface>::Connectors,
|
||||||
|
)>,
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
type Surface = EglSurface<B, D>;
|
type Surface = EglSurface<B, D>;
|
||||||
type Return = Rc<EglSurface<B, D>>;
|
type Return = Rc<EglSurface<B, D>>;
|
||||||
|
|
||||||
fn set_handler(&mut self, handler: impl DeviceHandler<Device=Self> + 'static) {
|
fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static) {
|
||||||
self.dev.borrow_mut().set_handler(InternalDeviceHandler {
|
self.dev.borrow_mut().set_handler(InternalDeviceHandler {
|
||||||
handler: Box::new(handler),
|
handler: Box::new(handler),
|
||||||
backends: Rc::downgrade(&self.backends),
|
backends: Rc::downgrade(&self.backends),
|
||||||
logger: self.logger.clone(),
|
logger: self.logger.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_handler(&mut self) {
|
fn clear_handler(&mut self) {
|
||||||
self.dev.borrow_mut().clear_handler()
|
self.dev.borrow_mut().clear_handler()
|
||||||
}
|
}
|
||||||
|
@ -147,7 +168,10 @@ impl<B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDis
|
||||||
) -> Result<Rc<EglSurface<B, D>>> {
|
) -> Result<Rc<EglSurface<B, D>>> {
|
||||||
info!(self.logger, "Initializing EglSurface");
|
info!(self.logger, "Initializing EglSurface");
|
||||||
|
|
||||||
let surface = self.dev.borrow_mut().create_surface((crtc, mode, connectors.into()).into())?;
|
let surface = self
|
||||||
|
.dev
|
||||||
|
.borrow_mut()
|
||||||
|
.create_surface((crtc, mode, connectors.into()).into())?;
|
||||||
|
|
||||||
let backend = Rc::new(EglSurface {
|
let backend = Rc::new(EglSurface {
|
||||||
dev: self.dev.clone(),
|
dev: self.dev.clone(),
|
||||||
|
@ -157,16 +181,17 @@ impl<B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDis
|
||||||
Ok(backend)
|
Ok(backend)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn process_events(&mut self) {
|
fn process_events(&mut self) {
|
||||||
self.dev.borrow_mut().process_events()
|
self.dev.borrow_mut().process_events()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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> + 'static>
|
||||||
where <D as Device>::Surface: NativeSurface
|
EGLGraphicsBackend for EglDevice<B, D>
|
||||||
|
where
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> {
|
fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> {
|
||||||
self.dev.borrow().bind_wl_display(display)
|
self.dev.borrow().bind_wl_display(display)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::os::unix::io::RawFd;
|
use std::os::unix::io::RawFd;
|
||||||
|
|
||||||
|
use super::EglDevice;
|
||||||
|
use backend::drm::Device;
|
||||||
use backend::egl::native::{Backend, NativeDisplay, NativeSurface};
|
use backend::egl::native::{Backend, NativeDisplay, NativeSurface};
|
||||||
use backend::session::{AsSessionObserver, SessionObserver};
|
use backend::session::{AsSessionObserver, SessionObserver};
|
||||||
use backend::drm::Device;
|
|
||||||
use super::{EglDevice};
|
|
||||||
|
|
||||||
/// `SessionObserver` linked to the `DrmDevice` it was created from.
|
/// `SessionObserver` linked to the `DrmDevice` it was created from.
|
||||||
pub struct EglDeviceObserver<S: SessionObserver + 'static> {
|
pub struct EglDeviceObserver<S: SessionObserver + 'static> {
|
||||||
|
@ -11,11 +11,12 @@ 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> + AsSessionObserver<S> + 'static,
|
||||||
> AsSessionObserver<EglDeviceObserver<S>> for EglDevice<B, D>
|
> AsSessionObserver<EglDeviceObserver<S>> for EglDevice<B, D>
|
||||||
where <D as Device>::Surface: NativeSurface
|
where
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
fn observer(&mut self) -> EglDeviceObserver<S> {
|
fn observer(&mut self) -> EglDeviceObserver<S> {
|
||||||
EglDeviceObserver {
|
EglDeviceObserver {
|
||||||
|
|
|
@ -3,22 +3,27 @@ use nix::libc::c_void;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use backend::drm::{Device, Surface};
|
|
||||||
use backend::egl::{EGLContext, EGLSurface};
|
|
||||||
use backend::egl::native::{Backend, NativeDisplay, NativeSurface};
|
|
||||||
use backend::graphics::{CursorBackend, SwapBuffersError};
|
|
||||||
use backend::graphics::gl::{GLGraphicsBackend, PixelFormat};
|
|
||||||
use super::error::*;
|
use super::error::*;
|
||||||
|
use backend::drm::{Device, Surface};
|
||||||
|
use backend::egl::native::{Backend, NativeDisplay, NativeSurface};
|
||||||
|
use backend::egl::{EGLContext, EGLSurface};
|
||||||
|
use backend::graphics::gl::{GLGraphicsBackend, PixelFormat};
|
||||||
|
use backend::graphics::{CursorBackend, SwapBuffersError};
|
||||||
|
|
||||||
pub struct EglSurface<B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
|
pub struct EglSurface<
|
||||||
where <D as Device>::Surface: NativeSurface
|
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||||
|
D: Device + NativeDisplay<B> + 'static,
|
||||||
|
> where
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
pub(in super) dev: Rc<RefCell<EGLContext<B, D>>>,
|
pub(super) dev: Rc<RefCell<EGLContext<B, D>>>,
|
||||||
pub(in super) surface: EGLSurface<B::Surface>,
|
pub(super) surface: EGLSurface<B::Surface>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> Surface for EglSurface<B, D>
|
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> Surface
|
||||||
where <D as Device>::Surface: NativeSurface
|
for EglSurface<B, D>
|
||||||
|
where
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Connectors = <<D as Device>::Surface as Surface>::Connectors;
|
type Connectors = <<D as Device>::Surface as Surface>::Connectors;
|
||||||
|
@ -30,36 +35,43 @@ impl<B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDis
|
||||||
fn current_connectors(&self) -> Self::Connectors {
|
fn current_connectors(&self) -> Self::Connectors {
|
||||||
self.surface.current_connectors()
|
self.surface.current_connectors()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_connectors(&self) -> Self::Connectors {
|
fn pending_connectors(&self) -> Self::Connectors {
|
||||||
self.surface.pending_connectors()
|
self.surface.pending_connectors()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_connector(&self, connector: connector::Handle) -> Result<()> {
|
fn add_connector(&self, connector: connector::Handle) -> Result<()> {
|
||||||
self.surface.add_connector(connector).chain_err(|| ErrorKind::UnderlyingBackendError)
|
self.surface
|
||||||
|
.add_connector(connector)
|
||||||
|
.chain_err(|| ErrorKind::UnderlyingBackendError)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_connector(&self, connector: connector::Handle) -> Result<()> {
|
fn remove_connector(&self, connector: connector::Handle) -> Result<()> {
|
||||||
self.surface.remove_connector(connector).chain_err(|| ErrorKind::UnderlyingBackendError)
|
self.surface
|
||||||
|
.remove_connector(connector)
|
||||||
|
.chain_err(|| ErrorKind::UnderlyingBackendError)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn current_mode(&self) -> Mode {
|
fn current_mode(&self) -> Mode {
|
||||||
self.surface.current_mode()
|
self.surface.current_mode()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_mode(&self) -> Mode {
|
fn pending_mode(&self) -> Mode {
|
||||||
self.surface.pending_mode()
|
self.surface.pending_mode()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn use_mode(&self, mode: Mode) -> Result<()> {
|
fn use_mode(&self, mode: Mode) -> Result<()> {
|
||||||
self.surface.use_mode(mode).chain_err(|| ErrorKind::UnderlyingBackendError)
|
self.surface
|
||||||
|
.use_mode(mode)
|
||||||
|
.chain_err(|| ErrorKind::UnderlyingBackendError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> CursorBackend<'a> for EglSurface<B, D>
|
impl<'a, B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
|
||||||
where
|
CursorBackend<'a> for EglSurface<B, D>
|
||||||
D: CursorBackend<'a>,
|
where
|
||||||
<D as Device>::Surface: NativeSurface
|
D: CursorBackend<'a>,
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
type CursorFormat = <D as CursorBackend<'a>>::CursorFormat;
|
type CursorFormat = <D as CursorBackend<'a>>::CursorFormat;
|
||||||
type Error = <D as CursorBackend<'a>>::Error;
|
type Error = <D as CursorBackend<'a>>::Error;
|
||||||
|
@ -73,15 +85,18 @@ impl<'a, B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + Nativ
|
||||||
buffer: Self::CursorFormat,
|
buffer: Self::CursorFormat,
|
||||||
hotspot: (u32, u32),
|
hotspot: (u32, u32),
|
||||||
) -> ::std::result::Result<(), Self::Error>
|
) -> ::std::result::Result<(), Self::Error>
|
||||||
where 'a: 'b
|
where
|
||||||
|
'a: 'b,
|
||||||
{
|
{
|
||||||
let dev = self.dev.borrow();
|
let dev = self.dev.borrow();
|
||||||
dev.set_cursor_representation(buffer, hotspot)
|
dev.set_cursor_representation(buffer, hotspot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static> GLGraphicsBackend for EglSurface<B, D>
|
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
|
||||||
where <D as Device>::Surface: NativeSurface
|
GLGraphicsBackend for EglSurface<B, D>
|
||||||
|
where
|
||||||
|
<D as Device>::Surface: NativeSurface,
|
||||||
{
|
{
|
||||||
fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> {
|
fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> {
|
||||||
self.surface.swap_buffers()
|
self.surface.swap_buffers()
|
||||||
|
@ -107,4 +122,4 @@ impl<B: Backend<Surface=<D as Device>::Surface> + 'static, D: Device + NativeDis
|
||||||
fn get_pixel_format(&self) -> PixelFormat {
|
fn get_pixel_format(&self) -> PixelFormat {
|
||||||
self.dev.borrow().get_pixel_format()
|
self.dev.borrow().get_pixel_format()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
use backend::drm::{RawDevice, Device, RawSurface, Surface};
|
use backend::drm::{Device, RawDevice, RawSurface, Surface};
|
||||||
use backend::egl::native::{Backend, NativeDisplay, NativeSurface};
|
use backend::egl::error::Result as EglResult;
|
||||||
use backend::egl::error::{Result as EglResult};
|
|
||||||
use backend::egl::ffi;
|
use backend::egl::ffi;
|
||||||
|
use backend::egl::native::{Backend, NativeDisplay, NativeSurface};
|
||||||
use backend::graphics::SwapBuffersError;
|
use backend::graphics::SwapBuffersError;
|
||||||
|
|
||||||
use super::{GbmDevice, GbmSurface};
|
|
||||||
use super::error::{Error, Result};
|
use super::error::{Error, Result};
|
||||||
|
use super::{GbmDevice, GbmSurface};
|
||||||
|
|
||||||
use drm::control::{crtc, Device as ControlDevice, Mode};
|
use drm::control::{crtc, Device as ControlDevice, Mode};
|
||||||
use gbm::AsRaw;
|
use gbm::AsRaw;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// Gbm backend type
|
/// Gbm backend type
|
||||||
pub struct Gbm<D: RawDevice + 'static>
|
pub struct Gbm<D: RawDevice + 'static>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
_userdata: PhantomData<D>,
|
_userdata: PhantomData<D>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: RawDevice + 'static> Backend for Gbm<D>
|
impl<D: RawDevice + 'static> Backend for Gbm<D>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
type Surface = Rc<GbmSurface<D>>;
|
type Surface = Rc<GbmSurface<D>>;
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ where
|
||||||
/// Arguments necessary to construct a `GbmSurface`
|
/// Arguments necessary to construct a `GbmSurface`
|
||||||
pub struct SurfaceArguments<D: RawDevice + 'static>
|
pub struct SurfaceArguments<D: RawDevice + 'static>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
/// Crtc
|
/// Crtc
|
||||||
pub crtc: crtc::Handle,
|
pub crtc: crtc::Handle,
|
||||||
|
@ -64,9 +64,10 @@ where
|
||||||
pub connectors: <GbmSurface<D> as Surface>::Connectors,
|
pub connectors: <GbmSurface<D> as Surface>::Connectors,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: RawDevice + 'static> From<(crtc::Handle, Mode, <GbmSurface<D> as Surface>::Connectors)> for SurfaceArguments<D>
|
impl<D: RawDevice + 'static> From<(crtc::Handle, Mode, <GbmSurface<D> as Surface>::Connectors)>
|
||||||
|
for SurfaceArguments<D>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<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 {
|
fn from((crtc, mode, connectors): (crtc::Handle, Mode, <GbmSurface<D> as Surface>::Connectors)) -> Self {
|
||||||
SurfaceArguments {
|
SurfaceArguments {
|
||||||
|
@ -79,7 +80,7 @@ where
|
||||||
|
|
||||||
unsafe impl<D: RawDevice + ControlDevice + 'static> NativeDisplay<Gbm<D>> for GbmDevice<D>
|
unsafe impl<D: RawDevice + ControlDevice + 'static> NativeDisplay<Gbm<D>> for GbmDevice<D>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
type Arguments = SurfaceArguments<D>;
|
type Arguments = SurfaceArguments<D>;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
@ -99,7 +100,7 @@ where
|
||||||
|
|
||||||
unsafe impl<D: RawDevice + 'static> NativeSurface for Rc<GbmSurface<D>>
|
unsafe impl<D: RawDevice + 'static> NativeSurface for Rc<GbmSurface<D>>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
fn ptr(&self) -> ffi::NativeWindowType {
|
fn ptr(&self) -> ffi::NativeWindowType {
|
||||||
self.surface.borrow().as_raw() as *const _
|
self.surface.borrow().as_raw() as *const _
|
||||||
|
@ -107,7 +108,7 @@ where
|
||||||
|
|
||||||
fn swap_buffers<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
|
fn swap_buffers<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>
|
F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
|
||||||
{
|
{
|
||||||
if ::std::borrow::Borrow::borrow(&self.crtc).commit_pending() {
|
if ::std::borrow::Borrow::borrow(&self.crtc).commit_pending() {
|
||||||
self.recreate(flip).map_err(|_| SwapBuffersError::ContextLost)
|
self.recreate(flip).map_err(|_| SwapBuffersError::ContextLost)
|
||||||
|
@ -115,4 +116,4 @@ where
|
||||||
self.page_flip(flip)
|
self.page_flip(flip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,19 +9,19 @@ error_chain! {
|
||||||
description("Creation of gbm device failed"),
|
description("Creation of gbm device failed"),
|
||||||
display("Creation of gbm device failed"),
|
display("Creation of gbm device failed"),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "Creation of gbm surface failed"]
|
#[doc = "Creation of gbm surface failed"]
|
||||||
SurfaceCreationFailed {
|
SurfaceCreationFailed {
|
||||||
description("Creation of gbm surface failed"),
|
description("Creation of gbm surface failed"),
|
||||||
display("Creation of gbm surface failed"),
|
display("Creation of gbm surface failed"),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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"),
|
||||||
display("Creation of gbm buffer object failed"),
|
display("Creation of gbm buffer object failed"),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "Writing to gbm buffer failed"]
|
#[doc = "Writing to gbm buffer failed"]
|
||||||
BufferWriteFailed {
|
BufferWriteFailed {
|
||||||
description("Writing to gbm buffer failed"),
|
description("Writing to gbm buffer failed"),
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use super::{Device, RawDevice, Surface, DeviceHandler};
|
use super::{Device, DeviceHandler, RawDevice, Surface};
|
||||||
|
|
||||||
use drm::control::{crtc, framebuffer, Device as ControlDevice, Mode};
|
use drm::control::{crtc, framebuffer, Device as ControlDevice, Mode};
|
||||||
use gbm::{self, Format as GbmFormat, BufferObjectFlags};
|
use gbm::{self, BufferObjectFlags, Format as GbmFormat};
|
||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use std::rc::{Rc, Weak};
|
use std::rc::{Rc, Weak};
|
||||||
use std::sync::{Once, ONCE_INIT};
|
use std::sync::{Once, ONCE_INIT};
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
use self::error::*;
|
use self::error::*;
|
||||||
|
@ -25,16 +25,16 @@ static LOAD: Once = ONCE_INIT;
|
||||||
/// Representation of an open gbm device to create rendering backends
|
/// Representation of an open gbm device to create rendering backends
|
||||||
pub struct GbmDevice<D: RawDevice + ControlDevice + 'static>
|
pub struct GbmDevice<D: RawDevice + ControlDevice + 'static>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
pub(in self) dev: Rc<RefCell<gbm::Device<D>>>,
|
pub(self) dev: Rc<RefCell<gbm::Device<D>>>,
|
||||||
backends: Rc<RefCell<HashMap<crtc::Handle, Weak<GbmSurface<D>>>>>,
|
backends: Rc<RefCell<HashMap<crtc::Handle, Weak<GbmSurface<D>>>>>,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: RawDevice + ControlDevice + 'static> GbmDevice<D>
|
impl<D: RawDevice + ControlDevice + 'static> GbmDevice<D>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
/// Create a new `GbmDevice` from an open drm node
|
/// Create a new `GbmDevice` from an open drm node
|
||||||
///
|
///
|
||||||
|
@ -56,7 +56,7 @@ where
|
||||||
nix::libc::RTLD_LAZY | nix::libc::RTLD_GLOBAL,
|
nix::libc::RTLD_LAZY | nix::libc::RTLD_GLOBAL,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_gbm"));
|
let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_gbm"));
|
||||||
|
|
||||||
dev.clear_handler();
|
dev.clear_handler();
|
||||||
|
@ -64,7 +64,9 @@ where
|
||||||
debug!(log, "Creating gbm device");
|
debug!(log, "Creating gbm device");
|
||||||
Ok(GbmDevice {
|
Ok(GbmDevice {
|
||||||
// Open the gbm device from the drm device
|
// Open the gbm device from the drm device
|
||||||
dev: Rc::new(RefCell::new(gbm::Device::new(dev).chain_err(|| ErrorKind::InitFailed)?)),
|
dev: Rc::new(RefCell::new(
|
||||||
|
gbm::Device::new(dev).chain_err(|| ErrorKind::InitFailed)?,
|
||||||
|
)),
|
||||||
backends: Rc::new(RefCell::new(HashMap::new())),
|
backends: Rc::new(RefCell::new(HashMap::new())),
|
||||||
logger: log,
|
logger: log,
|
||||||
})
|
})
|
||||||
|
@ -73,16 +75,16 @@ where
|
||||||
|
|
||||||
struct InternalDeviceHandler<D: RawDevice + ControlDevice + 'static>
|
struct InternalDeviceHandler<D: RawDevice + ControlDevice + 'static>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
handler: Box<DeviceHandler<Device=GbmDevice<D>> + 'static>,
|
handler: Box<DeviceHandler<Device = GbmDevice<D>> + 'static>,
|
||||||
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<GbmSurface<D>>>>>,
|
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<GbmSurface<D>>>>>,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: RawDevice + ControlDevice + 'static> DeviceHandler for InternalDeviceHandler<D>
|
impl<D: RawDevice + ControlDevice + 'static> DeviceHandler for InternalDeviceHandler<D>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
type Device = D;
|
type Device = D;
|
||||||
|
|
||||||
|
@ -94,30 +96,35 @@ where
|
||||||
self.handler.vblank(&*surface);
|
self.handler.vblank(&*surface);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn!(self.logger, "Surface ({:?}) not managed by gbm, event not handled.", surface.crtc());
|
warn!(
|
||||||
|
self.logger,
|
||||||
|
"Surface ({:?}) not managed by gbm, event not handled.",
|
||||||
|
surface.crtc()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn error(&mut self, error: <<D as Device>::Surface as Surface>::Error) {
|
fn error(&mut self, error: <<D as Device>::Surface as Surface>::Error) {
|
||||||
self.handler.error(ResultExt::<()>::chain_err(Err(error), || ErrorKind::UnderlyingBackendError).unwrap_err())
|
self.handler
|
||||||
|
.error(ResultExt::<()>::chain_err(Err(error), || ErrorKind::UnderlyingBackendError).unwrap_err())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D>
|
impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
type Surface = GbmSurface<D>;
|
type Surface = GbmSurface<D>;
|
||||||
type Return = Rc<GbmSurface<D>>;
|
type Return = Rc<GbmSurface<D>>;
|
||||||
|
|
||||||
fn set_handler(&mut self, handler: impl DeviceHandler<Device=Self> + 'static) {
|
fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static) {
|
||||||
self.dev.borrow_mut().set_handler(InternalDeviceHandler {
|
self.dev.borrow_mut().set_handler(InternalDeviceHandler {
|
||||||
handler: Box::new(handler),
|
handler: Box::new(handler),
|
||||||
backends: Rc::downgrade(&self.backends),
|
backends: Rc::downgrade(&self.backends),
|
||||||
logger: self.logger.clone(),
|
logger: self.logger.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_handler(&mut self) {
|
fn clear_handler(&mut self) {
|
||||||
self.dev.borrow_mut().clear_handler();
|
self.dev.borrow_mut().clear_handler();
|
||||||
}
|
}
|
||||||
|
@ -126,17 +133,20 @@ where
|
||||||
&mut self,
|
&mut self,
|
||||||
crtc: crtc::Handle,
|
crtc: crtc::Handle,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
connectors: impl Into<<Self::Surface as Surface>::Connectors>
|
connectors: impl Into<<Self::Surface as Surface>::Connectors>,
|
||||||
) -> Result<Rc<GbmSurface<D>>> {
|
) -> Result<Rc<GbmSurface<D>>> {
|
||||||
info!(self.logger, "Initializing GbmSurface");
|
info!(self.logger, "Initializing GbmSurface");
|
||||||
|
|
||||||
let (w, h) = mode.size();
|
let (w, h) = mode.size();
|
||||||
let surface = self.dev.borrow().create_surface(
|
let surface = self
|
||||||
w as u32,
|
.dev
|
||||||
h as u32,
|
.borrow()
|
||||||
GbmFormat::XRGB8888,
|
.create_surface(
|
||||||
BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
|
w as u32,
|
||||||
).chain_err(|| ErrorKind::SurfaceCreationFailed)?;
|
h as u32,
|
||||||
|
GbmFormat::XRGB8888,
|
||||||
|
BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
|
||||||
|
).chain_err(|| ErrorKind::SurfaceCreationFailed)?;
|
||||||
|
|
||||||
// init the first screen
|
// init the first screen
|
||||||
// (must be done before calling page_flip for the first time)
|
// (must be done before calling page_flip for the first time)
|
||||||
|
@ -147,11 +157,13 @@ where
|
||||||
debug!(self.logger, "FrontBuffer color format: {:?}", front_bo.format());
|
debug!(self.logger, "FrontBuffer color format: {:?}", front_bo.format());
|
||||||
|
|
||||||
// we need a framebuffer for the front buffer
|
// we need a framebuffer for the front buffer
|
||||||
let fb = framebuffer::create(&*self.dev.borrow(), &*front_bo).chain_err(|| ErrorKind::UnderlyingBackendError)?;
|
let fb = framebuffer::create(&*self.dev.borrow(), &*front_bo)
|
||||||
|
.chain_err(|| ErrorKind::UnderlyingBackendError)?;
|
||||||
front_bo.set_userdata(fb).unwrap();
|
front_bo.set_userdata(fb).unwrap();
|
||||||
|
|
||||||
let cursor = Cell::new((
|
let cursor = Cell::new((
|
||||||
self.dev.borrow()
|
self.dev
|
||||||
|
.borrow()
|
||||||
.create_buffer_object(
|
.create_buffer_object(
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
|
@ -177,15 +189,15 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_events(&mut self) {
|
fn process_events(&mut self) {
|
||||||
self.dev.borrow_mut().process_events()
|
self.dev.borrow_mut().process_events()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: RawDevice + ControlDevice + 'static> AsRawFd for GbmDevice<D>
|
impl<D: RawDevice + ControlDevice + 'static> AsRawFd for GbmDevice<D>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
self.dev.borrow().as_raw_fd()
|
self.dev.borrow().as_raw_fd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,32 +2,29 @@ use drm::control::{crtc, Device as ControlDevice, ResourceInfo};
|
||||||
use gbm::BufferObject;
|
use gbm::BufferObject;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::{Rc, Weak};
|
|
||||||
use std::os::unix::io::RawFd;
|
use std::os::unix::io::RawFd;
|
||||||
|
use std::rc::{Rc, Weak};
|
||||||
|
|
||||||
use backend::session::{AsSessionObserver, SessionObserver};
|
|
||||||
use backend::drm::{Device, RawDevice, RawSurface};
|
|
||||||
use super::{GbmDevice, GbmSurface};
|
use super::{GbmDevice, GbmSurface};
|
||||||
|
use backend::drm::{Device, RawDevice, RawSurface};
|
||||||
|
use backend::session::{AsSessionObserver, SessionObserver};
|
||||||
|
|
||||||
/// `SessionObserver` linked to the `DrmDevice` it was created from.
|
/// `SessionObserver` linked to the `DrmDevice` it was created from.
|
||||||
pub struct GbmDeviceObserver<
|
pub struct GbmDeviceObserver<
|
||||||
S: SessionObserver + 'static,
|
S: SessionObserver + 'static,
|
||||||
D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static,
|
D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static,
|
||||||
>
|
> where
|
||||||
where
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
|
||||||
{
|
{
|
||||||
observer: S,
|
observer: S,
|
||||||
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<GbmSurface<D>>>>>,
|
backends: Weak<RefCell<HashMap<crtc::Handle, Weak<GbmSurface<D>>>>>,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<S: SessionObserver + 'static, D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static>
|
||||||
S: SessionObserver + 'static,
|
AsSessionObserver<GbmDeviceObserver<S, D>> for GbmDevice<D>
|
||||||
D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static,
|
|
||||||
> AsSessionObserver<GbmDeviceObserver<S, D>> for GbmDevice<D>
|
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
fn observer(&mut self) -> GbmDeviceObserver<S, D> {
|
fn observer(&mut self) -> GbmDeviceObserver<S, D> {
|
||||||
GbmDeviceObserver {
|
GbmDeviceObserver {
|
||||||
|
@ -38,12 +35,10 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<S: SessionObserver + 'static, D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static>
|
||||||
S: SessionObserver + 'static,
|
SessionObserver for GbmDeviceObserver<S, D>
|
||||||
D: RawDevice + ControlDevice + AsSessionObserver<S> + 'static,
|
|
||||||
> SessionObserver for GbmDeviceObserver<S, D>
|
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
fn pause(&mut self, devnum: Option<(u32, u32)>) {
|
fn pause(&mut self, devnum: Option<(u32, u32)>) {
|
||||||
self.observer.pause(devnum);
|
self.observer.pause(devnum);
|
||||||
|
@ -56,15 +51,17 @@ where
|
||||||
for (crtc, backend) in backends.borrow().iter() {
|
for (crtc, backend) in backends.borrow().iter() {
|
||||||
if let Some(backend) = backend.upgrade() {
|
if let Some(backend) = backend.upgrade() {
|
||||||
// restart rendering loop
|
// restart rendering loop
|
||||||
if let Err(err) =
|
if let Err(err) = ::std::borrow::Borrow::borrow(&backend.crtc)
|
||||||
::std::borrow::Borrow::borrow(&backend.crtc).page_flip(backend.current_frame_buffer.get().handle())
|
.page_flip(backend.current_frame_buffer.get().handle())
|
||||||
{
|
{
|
||||||
warn!(self.logger, "Failed to restart rendering loop. Error: {}", err);
|
warn!(self.logger, "Failed to restart rendering loop. Error: {}", err);
|
||||||
}
|
}
|
||||||
// reset cursor
|
// reset cursor
|
||||||
{
|
{
|
||||||
let &(ref cursor, ref hotspot): &(BufferObject<()>, (u32, u32)) =
|
let &(ref cursor, ref hotspot): &(
|
||||||
unsafe { &*backend.cursor.as_ptr() };
|
BufferObject<()>,
|
||||||
|
(u32, u32),
|
||||||
|
) = unsafe { &*backend.cursor.as_ptr() };
|
||||||
if crtc::set_cursor2(
|
if crtc::set_cursor2(
|
||||||
&*backend.dev.borrow(),
|
&*backend.dev.borrow(),
|
||||||
*crtc,
|
*crtc,
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
|
use super::super::{Device, RawDevice, RawSurface, Surface};
|
||||||
use super::error::*;
|
use super::error::*;
|
||||||
use super::super::{Device, RawDevice, Surface, RawSurface};
|
|
||||||
|
|
||||||
use drm::control::{crtc, connector, framebuffer, Mode, ResourceInfo};
|
use drm::control::{connector, crtc, framebuffer, Mode, ResourceInfo};
|
||||||
use gbm::{self, SurfaceBufferHandle, Format as GbmFormat, BufferObject, BufferObjectFlags};
|
use gbm::{self, BufferObject, BufferObjectFlags, Format as GbmFormat, SurfaceBufferHandle};
|
||||||
use image::{ImageBuffer, Rgba};
|
use image::{ImageBuffer, Rgba};
|
||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::rc::Rc;
|
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use backend::drm::legacy::{LegacyDrmDevice, LegacyDrmSurface};
|
use backend::drm::legacy::{LegacyDrmDevice, LegacyDrmSurface};
|
||||||
use backend::graphics::CursorBackend;
|
use backend::graphics::CursorBackend;
|
||||||
|
@ -15,23 +15,23 @@ use backend::graphics::SwapBuffersError;
|
||||||
|
|
||||||
pub struct GbmSurface<D: RawDevice + 'static>
|
pub struct GbmSurface<D: RawDevice + 'static>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
pub(in super) dev: Rc<RefCell<gbm::Device<D>>>,
|
pub(super) dev: Rc<RefCell<gbm::Device<D>>>,
|
||||||
pub(in super) surface: RefCell<gbm::Surface<framebuffer::Info>>,
|
pub(super) surface: RefCell<gbm::Surface<framebuffer::Info>>,
|
||||||
pub(in super) crtc: <D as Device>::Return,
|
pub(super) crtc: <D as Device>::Return,
|
||||||
pub(in super) cursor: Cell<(BufferObject<()>, (u32, u32))>,
|
pub(super) cursor: Cell<(BufferObject<()>, (u32, u32))>,
|
||||||
pub(in super) current_frame_buffer: Cell<framebuffer::Info>,
|
pub(super) current_frame_buffer: Cell<framebuffer::Info>,
|
||||||
pub(in super) front_buffer: Cell<SurfaceBufferHandle<framebuffer::Info>>,
|
pub(super) front_buffer: Cell<SurfaceBufferHandle<framebuffer::Info>>,
|
||||||
pub(in super) next_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>,
|
pub(super) next_buffer: Cell<Option<SurfaceBufferHandle<framebuffer::Info>>>,
|
||||||
pub(in super) logger: ::slog::Logger,
|
pub(super) logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: RawDevice + 'static> GbmSurface<D>
|
impl<D: RawDevice + 'static> GbmSurface<D>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
pub(in super) fn unlock_buffer(&self) {
|
pub(super) fn unlock_buffer(&self) {
|
||||||
// after the page swap is finished we need to release the rendered buffer.
|
// after the page swap is finished we need to release the rendered buffer.
|
||||||
// this is called from the PageFlipHandler
|
// this is called from the PageFlipHandler
|
||||||
if let Some(next_buffer) = self.next_buffer.replace(None) {
|
if let Some(next_buffer) = self.next_buffer.replace(None) {
|
||||||
|
@ -43,7 +43,7 @@ where
|
||||||
|
|
||||||
pub fn page_flip<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
|
pub fn page_flip<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>
|
F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
|
||||||
{
|
{
|
||||||
let res = {
|
let res = {
|
||||||
let nb = self.next_buffer.take();
|
let nb = self.next_buffer.take();
|
||||||
|
@ -53,10 +53,7 @@ where
|
||||||
};
|
};
|
||||||
if res {
|
if res {
|
||||||
// We cannot call lock_front_buffer anymore without releasing the previous buffer, which will happen when the page flip is done
|
// We cannot call lock_front_buffer anymore without releasing the previous buffer, which will happen when the page flip is done
|
||||||
warn!(
|
warn!(self.logger, "Tried to swap with an already queued flip");
|
||||||
self.logger,
|
|
||||||
"Tried to swap with an already queued flip"
|
|
||||||
);
|
|
||||||
return Err(SwapBuffersError::AlreadySwapped);
|
return Err(SwapBuffersError::AlreadySwapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,16 +96,13 @@ where
|
||||||
|
|
||||||
pub fn recreate<F>(&self, flip: F) -> Result<()>
|
pub fn recreate<F>(&self, flip: F) -> Result<()>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>
|
F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
|
||||||
{
|
{
|
||||||
let (w, h) = self.pending_mode().size();
|
let (w, h) = self.pending_mode().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.
|
||||||
debug!(
|
debug!(self.logger, "Reinitializing surface for new mode: {}:{}", w, h);
|
||||||
self.logger,
|
|
||||||
"Reinitializing surface for new mode: {}:{}", w, h
|
|
||||||
);
|
|
||||||
let surface = self
|
let surface = self
|
||||||
.dev
|
.dev
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
@ -125,7 +119,9 @@ where
|
||||||
{
|
{
|
||||||
if let Some(mut old_bo) = self.next_buffer.take() {
|
if let Some(mut old_bo) = self.next_buffer.take() {
|
||||||
if let Ok(Some(fb)) = old_bo.take_userdata() {
|
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(::std::borrow::Borrow::borrow(&self.crtc), fb.handle())
|
||||||
|
{
|
||||||
warn!(
|
warn!(
|
||||||
self.logger,
|
self.logger,
|
||||||
"Error releasing old back_buffer framebuffer: {:?}", err
|
"Error releasing old back_buffer framebuffer: {:?}", err
|
||||||
|
@ -142,17 +138,14 @@ where
|
||||||
.lock_front_buffer()
|
.lock_front_buffer()
|
||||||
.chain_err(|| ErrorKind::FrontBufferLockFailed)?;
|
.chain_err(|| ErrorKind::FrontBufferLockFailed)?;
|
||||||
|
|
||||||
debug!(
|
debug!(self.logger, "FrontBuffer color format: {:?}", front_bo.format());
|
||||||
self.logger,
|
|
||||||
"FrontBuffer color format: {:?}",
|
|
||||||
front_bo.format()
|
|
||||||
);
|
|
||||||
|
|
||||||
// we also need a new framebuffer for the front buffer
|
// 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(::std::borrow::Borrow::borrow(&self.crtc), &*front_bo)
|
||||||
.chain_err(|| ErrorKind::UnderlyingBackendError)?;
|
.chain_err(|| ErrorKind::UnderlyingBackendError)?;
|
||||||
|
|
||||||
::std::borrow::Borrow::borrow(&self.crtc).commit(fb.handle())
|
::std::borrow::Borrow::borrow(&self.crtc)
|
||||||
|
.commit(fb.handle())
|
||||||
.chain_err(|| ErrorKind::UnderlyingBackendError)?;
|
.chain_err(|| ErrorKind::UnderlyingBackendError)?;
|
||||||
|
|
||||||
front_bo.set_userdata(fb).unwrap();
|
front_bo.set_userdata(fb).unwrap();
|
||||||
|
@ -169,31 +162,28 @@ where
|
||||||
|
|
||||||
// Drop the old surface after cleanup
|
// Drop the old surface after cleanup
|
||||||
*self.surface.borrow_mut() = surface;
|
*self.surface.borrow_mut() = surface;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: RawDevice + 'static> Surface for GbmSurface<D>
|
impl<D: RawDevice + 'static> Surface for GbmSurface<D>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
type Connectors = <<D as Device>::Surface as Surface>::Connectors;
|
type Connectors = <<D as Device>::Surface as Surface>::Connectors;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn crtc(&self) -> crtc::Handle {
|
fn crtc(&self) -> crtc::Handle {
|
||||||
::std::borrow::Borrow::borrow(&self.crtc)
|
::std::borrow::Borrow::borrow(&self.crtc).crtc()
|
||||||
.crtc()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn current_connectors(&self) -> Self::Connectors {
|
fn current_connectors(&self) -> Self::Connectors {
|
||||||
::std::borrow::Borrow::borrow(&self.crtc)
|
::std::borrow::Borrow::borrow(&self.crtc).current_connectors()
|
||||||
.current_connectors()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_connectors(&self) -> Self::Connectors {
|
fn pending_connectors(&self) -> Self::Connectors {
|
||||||
::std::borrow::Borrow::borrow(&self.crtc)
|
::std::borrow::Borrow::borrow(&self.crtc).pending_connectors()
|
||||||
.pending_connectors()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_connector(&self, connector: connector::Handle) -> Result<()> {
|
fn add_connector(&self, connector: connector::Handle) -> Result<()> {
|
||||||
|
@ -207,15 +197,13 @@ where
|
||||||
.remove_connector(connector)
|
.remove_connector(connector)
|
||||||
.chain_err(|| ErrorKind::UnderlyingBackendError)
|
.chain_err(|| ErrorKind::UnderlyingBackendError)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn current_mode(&self) -> Mode {
|
fn current_mode(&self) -> Mode {
|
||||||
::std::borrow::Borrow::borrow(&self.crtc)
|
::std::borrow::Borrow::borrow(&self.crtc).current_mode()
|
||||||
.current_mode()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_mode(&self) -> Mode {
|
fn pending_mode(&self) -> Mode {
|
||||||
::std::borrow::Borrow::borrow(&self.crtc)
|
::std::borrow::Borrow::borrow(&self.crtc).pending_mode()
|
||||||
.pending_mode()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn use_mode(&self, mode: Mode) -> Result<()> {
|
fn use_mode(&self, mode: Mode) -> Result<()> {
|
||||||
|
@ -257,9 +245,9 @@ impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurface<LegacyDrmDevice<
|
||||||
|
|
||||||
fn set_cursor_position(&self, x: u32, y: u32) -> Result<()> {
|
fn set_cursor_position(&self, x: u32, y: u32) -> Result<()> {
|
||||||
ResultExt::chain_err(
|
ResultExt::chain_err(
|
||||||
::std::borrow::Borrow::<Rc<LegacyDrmSurface<A>>>::borrow(&self.crtc)
|
::std::borrow::Borrow::<Rc<LegacyDrmSurface<A>>>::borrow(&self.crtc).set_cursor_position(x, y),
|
||||||
.set_cursor_position(x, y),
|
|| ErrorKind::UnderlyingBackendError,
|
||||||
|| ErrorKind::UnderlyingBackendError)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_cursor_representation<'b>(
|
fn set_cursor_representation<'b>(
|
||||||
|
@ -267,7 +255,8 @@ impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurface<LegacyDrmDevice<
|
||||||
buffer: &ImageBuffer<Rgba<u8>, Vec<u8>>,
|
buffer: &ImageBuffer<Rgba<u8>, Vec<u8>>,
|
||||||
hotspot: (u32, u32),
|
hotspot: (u32, u32),
|
||||||
) -> Result<()>
|
) -> Result<()>
|
||||||
where 'a: 'b
|
where
|
||||||
|
'a: 'b,
|
||||||
{
|
{
|
||||||
let (w, h) = buffer.dimensions();
|
let (w, h) = buffer.dimensions();
|
||||||
debug!(self.logger, "Importing cursor");
|
debug!(self.logger, "Importing cursor");
|
||||||
|
@ -293,7 +282,8 @@ impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurface<LegacyDrmDevice<
|
||||||
ResultExt::chain_err(
|
ResultExt::chain_err(
|
||||||
::std::borrow::Borrow::<Rc<LegacyDrmSurface<A>>>::borrow(&self.crtc)
|
::std::borrow::Borrow::<Rc<LegacyDrmSurface<A>>>::borrow(&self.crtc)
|
||||||
.set_cursor_representation(&cursor, hotspot),
|
.set_cursor_representation(&cursor, hotspot),
|
||||||
|| ErrorKind::UnderlyingBackendError)?;
|
|| ErrorKind::UnderlyingBackendError,
|
||||||
|
)?;
|
||||||
|
|
||||||
// and store it
|
// and store it
|
||||||
self.cursor.set((cursor, hotspot));
|
self.cursor.set((cursor, hotspot));
|
||||||
|
@ -303,7 +293,7 @@ impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for GbmSurface<LegacyDrmDevice<
|
||||||
|
|
||||||
impl<D: RawDevice + 'static> Drop for GbmSurface<D>
|
impl<D: RawDevice + 'static> Drop for GbmSurface<D>
|
||||||
where
|
where
|
||||||
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>
|
<D as Device>::Return: ::std::borrow::Borrow<<D as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Drop framebuffers attached to the userdata of the gbm surface buffers.
|
// Drop framebuffers attached to the userdata of the gbm surface buffers.
|
||||||
|
@ -326,4 +316,4 @@ where
|
||||||
let _ = framebuffer::destroy(::std::borrow::Borrow::borrow(&self.crtc), fb.handle());
|
let _ = framebuffer::destroy(::std::borrow::Borrow::borrow(&self.crtc), fb.handle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
use super::{Device, RawDevice, Surface, DeviceHandler, DevPath};
|
use super::{DevPath, Device, DeviceHandler, RawDevice, Surface};
|
||||||
|
|
||||||
|
use drm::control::{connector, crtc, encoder, Device as ControlDevice, Mode, ResourceInfo};
|
||||||
use drm::Device as BasicDevice;
|
use drm::Device as BasicDevice;
|
||||||
use drm::control::{crtc, connector, encoder, Device as ControlDevice, Mode, ResourceInfo};
|
|
||||||
use nix::libc::dev_t;
|
use nix::libc::dev_t;
|
||||||
use nix::sys::stat::fstat;
|
use nix::sys::stat::fstat;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::rc::{Rc, Weak};
|
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::rc::{Rc, Weak};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
mod surface;
|
mod surface;
|
||||||
pub use self::surface::LegacyDrmSurface;
|
pub use self::surface::LegacyDrmSurface;
|
||||||
|
@ -29,7 +29,7 @@ pub struct LegacyDrmDevice<A: AsRawFd + 'static> {
|
||||||
active: Arc<AtomicBool>,
|
active: Arc<AtomicBool>,
|
||||||
old_state: HashMap<crtc::Handle, (crtc::Info, Vec<connector::Handle>)>,
|
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<LegacyDrmSurface<A>>>>>,
|
||||||
handler: Option<RefCell<Box<DeviceHandler<Device=LegacyDrmDevice<A>>>>>,
|
handler: Option<RefCell<Box<DeviceHandler<Device = LegacyDrmDevice<A>>>>>,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,10 +122,10 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
|
||||||
type Surface = LegacyDrmSurface<A>;
|
type Surface = LegacyDrmSurface<A>;
|
||||||
type Return = Rc<LegacyDrmSurface<A>>;
|
type Return = Rc<LegacyDrmSurface<A>>;
|
||||||
|
|
||||||
fn set_handler(&mut self, handler: impl DeviceHandler<Device=Self> + 'static) {
|
fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static) {
|
||||||
self.handler = Some(RefCell::new(Box::new(handler)));
|
self.handler = Some(RefCell::new(Box::new(handler)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_handler(&mut self) {
|
fn clear_handler(&mut self) {
|
||||||
let _ = self.handler.take();
|
let _ = self.handler.take();
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
|
||||||
&mut self,
|
&mut self,
|
||||||
crtc: crtc::Handle,
|
crtc: crtc::Handle,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
connectors: impl Into<<Self::Surface as Surface>::Connectors>
|
connectors: impl Into<<Self::Surface as Surface>::Connectors>,
|
||||||
) -> Result<Rc<LegacyDrmSurface<A>>> {
|
) -> Result<Rc<LegacyDrmSurface<A>>> {
|
||||||
if self.backends.borrow().contains_key(&crtc) {
|
if self.backends.borrow().contains_key(&crtc) {
|
||||||
bail!(ErrorKind::CrtcAlreadyInUse(crtc));
|
bail!(ErrorKind::CrtcAlreadyInUse(crtc));
|
||||||
|
@ -181,11 +181,8 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
|
||||||
|
|
||||||
// configuration is valid, the kernel will figure out the rest
|
// configuration is valid, the kernel will figure out the rest
|
||||||
let logger = self.logger.new(o!("crtc" => format!("{:?}", crtc)));
|
let logger = self.logger.new(o!("crtc" => format!("{:?}", crtc)));
|
||||||
|
|
||||||
let state = State {
|
let state = State { mode, connectors };
|
||||||
mode,
|
|
||||||
connectors,
|
|
||||||
};
|
|
||||||
|
|
||||||
let backend = Rc::new(LegacyDrmSurface {
|
let backend = Rc::new(LegacyDrmSurface {
|
||||||
dev: self.dev.clone(),
|
dev: self.dev.clone(),
|
||||||
|
@ -194,17 +191,24 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
|
||||||
pending: RwLock::new(state),
|
pending: RwLock::new(state),
|
||||||
logger,
|
logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.backends.borrow_mut().insert(crtc, Rc::downgrade(&backend));
|
self.backends.borrow_mut().insert(crtc, Rc::downgrade(&backend));
|
||||||
Ok(backend)
|
Ok(backend)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_events(&mut self) {
|
fn process_events(&mut self) {
|
||||||
match crtc::receive_events(self) {
|
match crtc::receive_events(self) {
|
||||||
Ok(events) => for event in events {
|
Ok(events) => for event in events {
|
||||||
if let crtc::Event::PageFlip(event) = event {
|
if let crtc::Event::PageFlip(event) = event {
|
||||||
if self.active.load(Ordering::SeqCst) {
|
if self.active.load(Ordering::SeqCst) {
|
||||||
if let Some(backend) = self.backends.borrow().get(&event.crtc).iter().flat_map(|x| x.upgrade()).next() {
|
if let Some(backend) = self
|
||||||
|
.backends
|
||||||
|
.borrow()
|
||||||
|
.get(&event.crtc)
|
||||||
|
.iter()
|
||||||
|
.flat_map(|x| x.upgrade())
|
||||||
|
.next()
|
||||||
|
{
|
||||||
trace!(self.logger, "Handling event for backend {:?}", event.crtc);
|
trace!(self.logger, "Handling event for backend {:?}", event.crtc);
|
||||||
if let Some(handler) = self.handler.as_ref() {
|
if let Some(handler) = self.handler.as_ref() {
|
||||||
handler.borrow_mut().vblank(&backend);
|
handler.borrow_mut().vblank(&backend);
|
||||||
|
@ -216,10 +220,12 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(err) => if let Some(handler) = self.handler.as_ref() {
|
Err(err) => if let Some(handler) = self.handler.as_ref() {
|
||||||
handler.borrow_mut().error(ResultExt::<()>::chain_err(Err(err), ||
|
handler.borrow_mut().error(
|
||||||
ErrorKind::DrmDev(format!("Error processing drm events on {:?}", self.dev_path()))
|
ResultExt::<()>::chain_err(Err(err), || {
|
||||||
).unwrap_err());
|
ErrorKind::DrmDev(format!("Error processing drm events on {:?}", self.dev_path()))
|
||||||
}
|
}).unwrap_err(),
|
||||||
|
);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
|
use drm::control::{connector, crtc, Device as ControlDevice};
|
||||||
use drm::Device as BasicDevice;
|
use drm::Device as BasicDevice;
|
||||||
use drm::control::{crtc, connector, Device as ControlDevice};
|
|
||||||
use nix::libc::dev_t;
|
use nix::libc::dev_t;
|
||||||
use nix::sys::stat;
|
use nix::sys::stat;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::{Rc, Weak};
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
|
use std::rc::{Rc, Weak};
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use super::{Dev, LegacyDrmDevice, LegacyDrmSurface};
|
||||||
use backend::session::{AsSessionObserver, SessionObserver};
|
use backend::session::{AsSessionObserver, SessionObserver};
|
||||||
use super::{LegacyDrmDevice, LegacyDrmSurface, Dev};
|
|
||||||
|
|
||||||
/// `SessionObserver` linked to the `DrmDevice` it was created from.
|
/// `SessionObserver` linked to the `DrmDevice` it was created from.
|
||||||
pub struct LegacyDrmDeviceObserver<A: AsRawFd + 'static> {
|
pub struct LegacyDrmDeviceObserver<A: AsRawFd + 'static> {
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
use drm::Device as BasicDevice;
|
|
||||||
use drm::control::{connector, crtc, encoder, framebuffer, Device as ControlDevice, Mode, ResourceInfo};
|
|
||||||
pub use drm::buffer::Buffer;
|
pub use drm::buffer::Buffer;
|
||||||
|
use drm::control::{connector, crtc, encoder, framebuffer, Device as ControlDevice, Mode, ResourceInfo};
|
||||||
|
use drm::Device as BasicDevice;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::RwLock;
|
use std::sync::RwLock;
|
||||||
|
|
||||||
use backend::drm::{RawSurface, Surface, DevPath};
|
use backend::drm::{DevPath, RawSurface, Surface};
|
||||||
use backend::graphics::CursorBackend;
|
use backend::graphics::CursorBackend;
|
||||||
use backend::graphics::SwapBuffersError;
|
use backend::graphics::SwapBuffersError;
|
||||||
|
|
||||||
use super::{Dev, error::*};
|
use super::{error::*, Dev};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
|
@ -20,11 +20,11 @@ pub struct State {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LegacyDrmSurface<A: AsRawFd + 'static> {
|
pub struct LegacyDrmSurface<A: AsRawFd + 'static> {
|
||||||
pub(in super) dev: Rc<Dev<A>>,
|
pub(super) dev: Rc<Dev<A>>,
|
||||||
pub(in super) crtc: crtc::Handle,
|
pub(super) crtc: crtc::Handle,
|
||||||
pub(in super) state: RwLock<State>,
|
pub(super) state: RwLock<State>,
|
||||||
pub(in super) pending: RwLock<State>,
|
pub(super) pending: RwLock<State>,
|
||||||
pub(in super) logger: ::slog::Logger,
|
pub(super) logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: AsRawFd + 'static> AsRawFd for LegacyDrmSurface<A> {
|
impl<A: AsRawFd + 'static> AsRawFd for LegacyDrmSurface<A> {
|
||||||
|
@ -42,36 +42,19 @@ impl<'a, A: AsRawFd + 'static> CursorBackend<'a> for LegacyDrmSurface<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)).chain_err(|| {
|
crtc::move_cursor(self, self.crtc, (x as i32, y as i32))
|
||||||
ErrorKind::DrmDev(format!(
|
.chain_err(|| ErrorKind::DrmDev(format!("Error moving cursor on {:?}", self.dev_path())))
|
||||||
"Error moving cursor on {:?}",
|
|
||||||
self.dev_path()
|
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_cursor_representation<'b>(
|
fn set_cursor_representation<'b>(&'b self, buffer: Self::CursorFormat, hotspot: (u32, u32)) -> Result<()>
|
||||||
&'b self,
|
where
|
||||||
buffer: Self::CursorFormat,
|
'a: 'b,
|
||||||
hotspot: (u32, u32),
|
|
||||||
) -> Result<()>
|
|
||||||
where 'a: 'b
|
|
||||||
{
|
{
|
||||||
trace!(self.logger, "Setting the new imported cursor");
|
trace!(self.logger, "Setting the new imported cursor");
|
||||||
|
|
||||||
if crtc::set_cursor2(
|
if crtc::set_cursor2(self, self.crtc, buffer, (hotspot.0 as i32, hotspot.1 as i32)).is_err() {
|
||||||
self,
|
crtc::set_cursor(self, self.crtc, buffer)
|
||||||
self.crtc,
|
.chain_err(|| ErrorKind::DrmDev(format!("Failed to set cursor on {:?}", self.dev_path())))?;
|
||||||
buffer,
|
|
||||||
(hotspot.0 as i32, hotspot.1 as i32),
|
|
||||||
).is_err()
|
|
||||||
{
|
|
||||||
crtc::set_cursor(self, self.crtc, buffer).chain_err(|| {
|
|
||||||
ErrorKind::DrmDev(format!(
|
|
||||||
"Failed to set cursor on {:?}",
|
|
||||||
self.dev_path()
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -85,11 +68,11 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurface<A> {
|
||||||
fn crtc(&self) -> crtc::Handle {
|
fn crtc(&self) -> crtc::Handle {
|
||||||
self.crtc
|
self.crtc
|
||||||
}
|
}
|
||||||
|
|
||||||
fn current_connectors(&self) -> Self::Connectors {
|
fn current_connectors(&self) -> Self::Connectors {
|
||||||
self.state.read().unwrap().connectors.clone()
|
self.state.read().unwrap().connectors.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_connectors(&self) -> Self::Connectors {
|
fn pending_connectors(&self) -> Self::Connectors {
|
||||||
self.pending.read().unwrap().connectors.clone()
|
self.pending.read().unwrap().connectors.clone()
|
||||||
}
|
}
|
||||||
|
@ -104,10 +87,7 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurface<A> {
|
||||||
|
|
||||||
fn add_connector(&self, connector: connector::Handle) -> Result<()> {
|
fn add_connector(&self, connector: connector::Handle) -> Result<()> {
|
||||||
let info = connector::Info::load_from_device(self, connector).chain_err(|| {
|
let info = connector::Info::load_from_device(self, connector).chain_err(|| {
|
||||||
ErrorKind::DrmDev(format!(
|
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path()))
|
||||||
"Error loading connector info on {:?}",
|
|
||||||
self.dev_path()
|
|
||||||
))
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut pending = self.pending.write().unwrap();
|
let mut pending = self.pending.write().unwrap();
|
||||||
|
@ -120,28 +100,19 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurface<A> {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|encoder| {
|
.map(|encoder| {
|
||||||
encoder::Info::load_from_device(self, *encoder).chain_err(|| {
|
encoder::Info::load_from_device(self, *encoder).chain_err(|| {
|
||||||
ErrorKind::DrmDev(format!(
|
ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", self.dev_path()))
|
||||||
"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().chain_err(|| {
|
||||||
ErrorKind::DrmDev(format!(
|
ErrorKind::DrmDev(format!("Error loading resources on {:?}", self.dev_path()))
|
||||||
"Error loading resources on {:?}",
|
|
||||||
self.dev_path()
|
|
||||||
))
|
|
||||||
})?;
|
})?;
|
||||||
if !encoders
|
if !encoders
|
||||||
.iter()
|
.iter()
|
||||||
.map(|encoder| encoder.possible_crtcs())
|
.map(|encoder| encoder.possible_crtcs())
|
||||||
.all(|crtc_list| {
|
.all(|crtc_list| resource_handles.filter_crtcs(crtc_list).contains(&self.crtc))
|
||||||
resource_handles
|
{
|
||||||
.filter_crtcs(crtc_list)
|
|
||||||
.contains(&self.crtc)
|
|
||||||
}) {
|
|
||||||
bail!(ErrorKind::NoSuitableEncoder(info, self.crtc));
|
bail!(ErrorKind::NoSuitableEncoder(info, self.crtc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,15 +130,12 @@ impl<A: AsRawFd + 'static> Surface for LegacyDrmSurface<A> {
|
||||||
|
|
||||||
fn use_mode(&self, mode: Mode) -> Result<()> {
|
fn use_mode(&self, mode: 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 {
|
for connector in &pending.connectors {
|
||||||
if !connector::Info::load_from_device(self, *connector)
|
if !connector::Info::load_from_device(self, *connector)
|
||||||
.chain_err(|| {
|
.chain_err(|| {
|
||||||
ErrorKind::DrmDev(format!(
|
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path()))
|
||||||
"Error loading connector info on {:?}",
|
|
||||||
self.dev_path()
|
|
||||||
))
|
|
||||||
})?.modes()
|
})?.modes()
|
||||||
.contains(&mode)
|
.contains(&mode)
|
||||||
{
|
{
|
||||||
|
@ -185,7 +153,7 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurface<A> {
|
||||||
fn commit_pending(&self) -> bool {
|
fn commit_pending(&self) -> bool {
|
||||||
*self.pending.read().unwrap() != *self.state.read().unwrap()
|
*self.pending.read().unwrap() != *self.state.read().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commit(&self, framebuffer: framebuffer::Handle) -> Result<()> {
|
fn commit(&self, framebuffer: framebuffer::Handle) -> Result<()> {
|
||||||
let mut current = self.state.write().unwrap();
|
let mut current = self.state.write().unwrap();
|
||||||
let pending = self.pending.read().unwrap();
|
let pending = self.pending.read().unwrap();
|
||||||
|
@ -196,11 +164,7 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurface<A> {
|
||||||
|
|
||||||
for conn in removed {
|
for conn in removed {
|
||||||
if let Ok(info) = connector::Info::load_from_device(self, *conn) {
|
if let Ok(info) = connector::Info::load_from_device(self, *conn) {
|
||||||
info!(
|
info!(self.logger, "Removing connector: {:?}", info.connector_type());
|
||||||
self.logger,
|
|
||||||
"Removing connector: {:?}",
|
|
||||||
info.connector_type()
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
info!(self.logger, "Removing unknown connector");
|
info!(self.logger, "Removing unknown connector");
|
||||||
}
|
}
|
||||||
|
@ -208,11 +172,7 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurface<A> {
|
||||||
|
|
||||||
for conn in added {
|
for conn in added {
|
||||||
if let Ok(info) = connector::Info::load_from_device(self, *conn) {
|
if let Ok(info) = connector::Info::load_from_device(self, *conn) {
|
||||||
info!(
|
info!(self.logger, "Adding connector: {:?}", info.connector_type());
|
||||||
self.logger,
|
|
||||||
"Adding connector: {:?}",
|
|
||||||
info.connector_type()
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
info!(self.logger, "Adding unknown connector");
|
info!(self.logger, "Adding unknown connector");
|
||||||
}
|
}
|
||||||
|
@ -228,7 +188,11 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurface<A> {
|
||||||
self,
|
self,
|
||||||
self.crtc,
|
self.crtc,
|
||||||
framebuffer,
|
framebuffer,
|
||||||
&pending.connectors.iter().map(|x| *x).collect::<Vec<connector::Handle>>(),
|
&pending
|
||||||
|
.connectors
|
||||||
|
.iter()
|
||||||
|
.map(|x| *x)
|
||||||
|
.collect::<Vec<connector::Handle>>(),
|
||||||
(0, 0),
|
(0, 0),
|
||||||
Some(pending.mode),
|
Some(pending.mode),
|
||||||
).chain_err(|| {
|
).chain_err(|| {
|
||||||
|
@ -243,7 +207,7 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurface<A> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
use drm::Device as BasicDevice;
|
|
||||||
use drm::control::Device as ControlDevice;
|
|
||||||
pub use drm::control::crtc;
|
|
||||||
pub use drm::control::connector;
|
pub use drm::control::connector;
|
||||||
|
pub use drm::control::crtc;
|
||||||
pub use drm::control::framebuffer;
|
pub use drm::control::framebuffer;
|
||||||
|
use drm::control::Device as ControlDevice;
|
||||||
pub use drm::control::Mode;
|
pub use drm::control::Mode;
|
||||||
|
use drm::Device as BasicDevice;
|
||||||
|
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use wayland_server::calloop::generic::{EventedFd, Generic};
|
use wayland_server::calloop::generic::{EventedFd, Generic};
|
||||||
use wayland_server::calloop::{LoopHandle, Source};
|
|
||||||
use wayland_server::calloop::mio::Ready;
|
use wayland_server::calloop::mio::Ready;
|
||||||
pub use wayland_server::calloop::InsertError;
|
pub use wayland_server::calloop::InsertError;
|
||||||
|
use wayland_server::calloop::{LoopHandle, Source};
|
||||||
|
|
||||||
use super::graphics::SwapBuffersError;
|
use super::graphics::SwapBuffersError;
|
||||||
|
|
||||||
#[cfg(feature = "backend_drm_legacy")]
|
|
||||||
pub mod legacy;
|
|
||||||
#[cfg(feature = "backend_drm_gbm")]
|
|
||||||
pub mod gbm;
|
|
||||||
#[cfg(feature = "backend_drm_egl")]
|
#[cfg(feature = "backend_drm_egl")]
|
||||||
pub mod egl;
|
pub mod egl;
|
||||||
|
#[cfg(feature = "backend_drm_gbm")]
|
||||||
|
pub mod gbm;
|
||||||
|
#[cfg(feature = "backend_drm_legacy")]
|
||||||
|
pub mod legacy;
|
||||||
|
|
||||||
pub trait DeviceHandler {
|
pub trait DeviceHandler {
|
||||||
type Device: Device + ?Sized;
|
type Device: Device + ?Sized;
|
||||||
|
@ -34,26 +34,26 @@ pub trait Device: AsRawFd + DevPath {
|
||||||
type Surface: Surface;
|
type Surface: Surface;
|
||||||
type Return: Borrow<Self::Surface>;
|
type Return: Borrow<Self::Surface>;
|
||||||
|
|
||||||
fn set_handler(&mut self, handler: impl DeviceHandler<Device=Self> + 'static);
|
fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static);
|
||||||
fn clear_handler(&mut self);
|
fn clear_handler(&mut self);
|
||||||
fn create_surface(
|
fn create_surface(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctrc: crtc::Handle,
|
ctrc: crtc::Handle,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
connectors: impl Into<<Self::Surface as Surface>::Connectors>
|
connectors: impl Into<<Self::Surface as Surface>::Connectors>,
|
||||||
) -> Result<Self::Return, <Self::Surface as Surface>::Error>;
|
) -> Result<Self::Return, <Self::Surface as Surface>::Error>;
|
||||||
fn process_events(&mut self);
|
fn process_events(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RawDevice: Device<Surface=<Self as RawDevice>::Surface>
|
pub trait RawDevice: Device<Surface = <Self as RawDevice>::Surface>
|
||||||
where
|
where
|
||||||
<Self as Device>::Return: Borrow<<Self as RawDevice>::Surface>
|
<Self as Device>::Return: Borrow<<Self as RawDevice>::Surface>,
|
||||||
{
|
{
|
||||||
type Surface: RawSurface;
|
type Surface: RawSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Surface {
|
pub trait Surface {
|
||||||
type Connectors: IntoIterator<Item=connector::Handle>;
|
type Connectors: IntoIterator<Item = connector::Handle>;
|
||||||
type Error: Error + Send;
|
type Error: Error + Send;
|
||||||
|
|
||||||
fn crtc(&self) -> crtc::Handle;
|
fn crtc(&self) -> crtc::Handle;
|
||||||
|
@ -70,7 +70,7 @@ pub trait RawSurface: Surface + ControlDevice + BasicDevice {
|
||||||
fn commit_pending(&self) -> bool;
|
fn commit_pending(&self) -> bool;
|
||||||
fn commit(&self, framebuffer: framebuffer::Handle) -> Result<(), <Self as Surface>::Error>;
|
fn commit(&self, framebuffer: framebuffer::Handle) -> Result<(), <Self as Surface>::Error>;
|
||||||
fn page_flip(&self, framebuffer: framebuffer::Handle) -> Result<(), SwapBuffersError>;
|
fn page_flip(&self, framebuffer: framebuffer::Handle) -> Result<(), SwapBuffersError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for types representing open devices
|
/// Trait for types representing open devices
|
||||||
pub trait DevPath {
|
pub trait DevPath {
|
||||||
|
@ -82,7 +82,7 @@ impl<A: AsRawFd> DevPath for A {
|
||||||
fn dev_path(&self) -> Option<PathBuf> {
|
fn dev_path(&self) -> Option<PathBuf> {
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
fs::read_link(format!("/proc/self/fd/{:?}", self.as_raw_fd())).ok()
|
fs::read_link(format!("/proc/self/fd/{:?}", self.as_raw_fd())).ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,14 +52,8 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
{
|
{
|
||||||
let log = ::slog_or_stdlog(logger.into()).new(o!("smithay_module" => "renderer_egl"));
|
let log = ::slog_or_stdlog(logger.into()).new(o!("smithay_module" => "renderer_egl"));
|
||||||
let ptr = native.ptr()?;
|
let ptr = native.ptr()?;
|
||||||
let (
|
let (context, display, config_id, surface_attributes, pixel_format, wl_drm_support) =
|
||||||
context,
|
unsafe { EGLContext::<B, N>::new_internal(ptr, attributes, reqs, log.clone()) }?;
|
||||||
display,
|
|
||||||
config_id,
|
|
||||||
surface_attributes,
|
|
||||||
pixel_format,
|
|
||||||
wl_drm_support,
|
|
||||||
) = unsafe { EGLContext::<B, N>::new_internal(ptr, attributes, reqs, log.clone()) }?;
|
|
||||||
|
|
||||||
Ok(EGLContext {
|
Ok(EGLContext {
|
||||||
native,
|
native,
|
||||||
|
@ -117,15 +111,15 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
bail!(ErrorKind::OpenGlVersionNotSupported(version));
|
bail!(ErrorKind::OpenGlVersionNotSupported(version));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn constrain<F>(f: F) -> F
|
|
||||||
where
|
|
||||||
F: for<'a> Fn(&'a str) -> *const ::std::os::raw::c_void,
|
|
||||||
{
|
|
||||||
f
|
|
||||||
};
|
|
||||||
|
|
||||||
ffi::egl::LOAD.call_once(|| {
|
ffi::egl::LOAD.call_once(|| {
|
||||||
|
fn constrain<F>(f: F) -> F
|
||||||
|
where
|
||||||
|
F: for<'a> Fn(&'a str) -> *const ::std::os::raw::c_void,
|
||||||
|
{
|
||||||
|
f
|
||||||
|
};
|
||||||
|
|
||||||
ffi::egl::load_with(|sym| {
|
ffi::egl::load_with(|sym| {
|
||||||
let name = CString::new(sym).unwrap();
|
let name = CString::new(sym).unwrap();
|
||||||
let symbol = ffi::egl::LIB.get::<*mut c_void>(name.as_bytes());
|
let symbol = ffi::egl::LIB.get::<*mut c_void>(name.as_bytes());
|
||||||
|
@ -144,7 +138,7 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
ffi::egl::UnbindWaylandDisplayWL::load_with(&proc_address);
|
ffi::egl::UnbindWaylandDisplayWL::load_with(&proc_address);
|
||||||
ffi::egl::QueryWaylandBufferWL::load_with(&proc_address);
|
ffi::egl::QueryWaylandBufferWL::load_with(&proc_address);
|
||||||
});
|
});
|
||||||
|
|
||||||
// the first step is to query the list of extensions without any display, if supported
|
// the first step is to query the list of extensions without any display, if supported
|
||||||
let dp_extensions = {
|
let dp_extensions = {
|
||||||
let p = ffi::egl::QueryString(ffi::egl::NO_DISPLAY, ffi::egl::EXTENSIONS as i32);
|
let p = ffi::egl::QueryString(ffi::egl::NO_DISPLAY, ffi::egl::EXTENSIONS as i32);
|
||||||
|
@ -437,13 +431,11 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
/// Creates a surface for rendering
|
/// Creates a surface for rendering
|
||||||
pub fn create_surface(&mut self, args: N::Arguments) -> Result<EGLSurface<B::Surface>> {
|
pub fn create_surface(&mut self, args: N::Arguments) -> Result<EGLSurface<B::Surface>> {
|
||||||
trace!(self.logger, "Creating EGL window surface.");
|
trace!(self.logger, "Creating EGL window surface.");
|
||||||
let surface = self.native
|
let surface = self
|
||||||
.create_surface(args)
|
.native
|
||||||
.chain_err(|| ErrorKind::SurfaceCreationFailed)?;
|
.create_surface(args)
|
||||||
EGLSurface::new(
|
.chain_err(|| ErrorKind::SurfaceCreationFailed)?;
|
||||||
self,
|
EGLSurface::new(self, surface).map(|x| {
|
||||||
surface,
|
|
||||||
).map(|x| {
|
|
||||||
debug!(self.logger, "EGL surface successfully created");
|
debug!(self.logger, "EGL surface successfully created");
|
||||||
x
|
x
|
||||||
})
|
})
|
||||||
|
|
|
@ -181,7 +181,9 @@ impl ::std::error::Error for TextureCreationError {
|
||||||
match *self {
|
match *self {
|
||||||
TextureCreationError::ContextLost => "The context has been lost, it needs to be recreated",
|
TextureCreationError::ContextLost => "The context has been lost, it needs to be recreated",
|
||||||
TextureCreationError::PlaneIndexOutOfBounds => "This buffer is not managed by EGL",
|
TextureCreationError::PlaneIndexOutOfBounds => "This buffer is not managed by EGL",
|
||||||
TextureCreationError::GLExtensionNotSupported(_) => "Required OpenGL Extension for texture creation is missing",
|
TextureCreationError::GLExtensionNotSupported(_) => {
|
||||||
|
"Required OpenGL Extension for texture creation is missing"
|
||||||
|
}
|
||||||
TextureCreationError::TextureBindingFailed(_) => "Failed to create EGLImages from the buffer",
|
TextureCreationError::TextureBindingFailed(_) => "Failed to create EGLImages from the buffer",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,7 +265,7 @@ impl EGLImages {
|
||||||
if !self.egl_to_texture_support {
|
if !self.egl_to_texture_support {
|
||||||
return Err(TextureCreationError::GLExtensionNotSupported("GL_OES_EGL_image"));
|
return Err(TextureCreationError::GLExtensionNotSupported("GL_OES_EGL_image"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut old_tex_id: i32 = 0;
|
let mut old_tex_id: i32 = 0;
|
||||||
self.gl.GetIntegerv(gl_ffi::TEXTURE_BINDING_2D, &mut old_tex_id);
|
self.gl.GetIntegerv(gl_ffi::TEXTURE_BINDING_2D, &mut old_tex_id);
|
||||||
self.gl.BindTexture(gl_ffi::TEXTURE_2D, tex_id);
|
self.gl.BindTexture(gl_ffi::TEXTURE_2D, tex_id);
|
||||||
|
@ -343,11 +345,12 @@ impl EGLDisplay {
|
||||||
#[cfg(feature = "renderer_gl")]
|
#[cfg(feature = "renderer_gl")]
|
||||||
egl_to_texture_support: {
|
egl_to_texture_support: {
|
||||||
// the list of gl extensions supported by the context
|
// the list of gl extensions supported by the context
|
||||||
let data = unsafe { CStr::from_ptr(gl.GetString(gl_ffi::EXTENSIONS) as *const _ )}
|
let data = unsafe { CStr::from_ptr(gl.GetString(gl_ffi::EXTENSIONS) as *const _) }
|
||||||
.to_bytes()
|
.to_bytes()
|
||||||
.to_vec();
|
.to_vec();
|
||||||
let list = String::from_utf8(data).unwrap();
|
let list = String::from_utf8(data).unwrap();
|
||||||
list.split(' ').any(|s| s == "GL_OES_EGL_image" || s == "GL_OES_EGL_image_base")
|
list.split(' ')
|
||||||
|
.any(|s| s == "GL_OES_EGL_image" || s == "GL_OES_EGL_image_base")
|
||||||
},
|
},
|
||||||
#[cfg(feature = "renderer_gl")]
|
#[cfg(feature = "renderer_gl")]
|
||||||
gl,
|
gl,
|
||||||
|
@ -496,4 +499,4 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLGraphicsBackend for EGL
|
||||||
}
|
}
|
||||||
Ok(EGLDisplay::new(self, display.c_ptr()))
|
Ok(EGLDisplay::new(self, display.c_ptr()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,9 +169,10 @@ pub unsafe trait NativeSurface {
|
||||||
fn ptr(&self) -> ffi::NativeWindowType;
|
fn ptr(&self) -> ffi::NativeWindowType;
|
||||||
/// Adds additional semantics when calling EGLSurface::swap_buffers
|
/// Adds additional semantics when calling EGLSurface::swap_buffers
|
||||||
///
|
///
|
||||||
/// Only implement if required by the backend, flip must be called during this call.
|
/// Only implement if required by the backend, flip must be called during this call.
|
||||||
fn swap_buffers<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
|
fn swap_buffers<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
|
||||||
where F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>
|
where
|
||||||
|
F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>,
|
||||||
{
|
{
|
||||||
flip()
|
flip()
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ impl<N: native::NativeSurface> EGLSurface<N> {
|
||||||
err => Err(SwapBuffersError::Unknown(err)),
|
err => Err(SwapBuffersError::Unknown(err)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(SwapBuffersError::ContextLost)
|
Err(SwapBuffersError::ContextLost)
|
||||||
|
|
|
@ -29,5 +29,6 @@ pub trait CursorBackend<'a> {
|
||||||
cursor: Self::CursorFormat,
|
cursor: Self::CursorFormat,
|
||||||
hotspot: (u32, u32),
|
hotspot: (u32, u32),
|
||||||
) -> Result<(), Self::Error>
|
) -> Result<(), Self::Error>
|
||||||
where 'a: 'b;
|
where
|
||||||
}
|
'a: 'b;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::fmt;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
/// Error that can happen when swapping buffers.
|
/// Error that can happen when swapping buffers.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
@ -43,4 +43,3 @@ impl Error for SwapBuffersError {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,10 +67,10 @@ pub trait GLGraphicsBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a Raw GLES Interface for a given `GLGraphicsBackend`
|
/// Loads a Raw GLES Interface for a given `GLGraphicsBackend`
|
||||||
///
|
///
|
||||||
/// This remains valid as long as the underlying `GLGraphicsBackend` is alive
|
/// This remains valid as long as the underlying `GLGraphicsBackend` is alive
|
||||||
/// and may only be used in combination with the backend. Using this with any
|
/// and may only be used in combination with the backend. Using this with any
|
||||||
/// other gl context may cause undefined behavior.
|
/// other gl context may cause undefined behavior.
|
||||||
pub fn load_raw_gl<B: GLGraphicsBackend>(backend: &B) -> Gles2 {
|
pub fn load_raw_gl<B: GLGraphicsBackend>(backend: &B) -> Gles2 {
|
||||||
Gles2::load_with(|s| unsafe { backend.get_proc_address(s) as *const _ })
|
Gles2::load_with(|s| unsafe { backend.get_proc_address(s) as *const _ })
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
//! Glium compatibility module
|
//! Glium compatibility module
|
||||||
|
|
||||||
use backend::graphics::{
|
use backend::graphics::{gl::GLGraphicsBackend, SwapBuffersError};
|
||||||
gl::GLGraphicsBackend,
|
|
||||||
SwapBuffersError,
|
|
||||||
};
|
|
||||||
use glium::{
|
use glium::{
|
||||||
backend::{Backend, Context, Facade},
|
backend::{Backend, Context, Facade},
|
||||||
debug::DebugCallbackBehavior,
|
debug::DebugCallbackBehavior,
|
||||||
|
|
|
@ -16,13 +16,16 @@ use std::{
|
||||||
use wayland_server::calloop::{
|
use wayland_server::calloop::{
|
||||||
generic::{EventedFd, Generic},
|
generic::{EventedFd, Generic},
|
||||||
mio::Ready,
|
mio::Ready,
|
||||||
LoopHandle, Source, InsertError,
|
InsertError, LoopHandle, Source,
|
||||||
};
|
};
|
||||||
|
|
||||||
// No idea if this is the same across unix platforms
|
// No idea if this is the same across unix platforms
|
||||||
// Lets make this linux exclusive for now, once someone tries to build it for
|
// Lets make this linux exclusive for now, once someone tries to build it for
|
||||||
// any BSD-like system, they can verify if this is right and make a PR to change this.
|
// any BSD-like system, they can verify if this is right and make a PR to change this.
|
||||||
#[cfg(all(any(target_os = "linux", target_os = "android"), feature = "backend_session"))]
|
#[cfg(all(
|
||||||
|
any(target_os = "linux", target_os = "android"),
|
||||||
|
feature = "backend_session"
|
||||||
|
))]
|
||||||
const INPUT_MAJOR: u32 = 13;
|
const INPUT_MAJOR: u32 = 13;
|
||||||
|
|
||||||
/// Libinput based `InputBackend`.
|
/// Libinput based `InputBackend`.
|
||||||
|
@ -600,13 +603,16 @@ impl AsRawFd for LibinputInputBackend {
|
||||||
pub fn libinput_bind<Data: 'static>(
|
pub fn libinput_bind<Data: 'static>(
|
||||||
backend: LibinputInputBackend,
|
backend: LibinputInputBackend,
|
||||||
handle: LoopHandle<Data>,
|
handle: LoopHandle<Data>,
|
||||||
) -> ::std::result::Result<Source<Generic<EventedFd<LibinputInputBackend>>>, InsertError<Generic<EventedFd<LibinputInputBackend>>>> {
|
) -> ::std::result::Result<
|
||||||
|
Source<Generic<EventedFd<LibinputInputBackend>>>,
|
||||||
|
InsertError<Generic<EventedFd<LibinputInputBackend>>>,
|
||||||
|
> {
|
||||||
let mut source = Generic::from_fd_source(backend);
|
let mut source = Generic::from_fd_source(backend);
|
||||||
source.set_interest(Ready::readable());
|
source.set_interest(Ready::readable());
|
||||||
|
|
||||||
handle.insert_source(source, move |evt, _| {
|
handle.insert_source(source, move |evt, _| {
|
||||||
use backend::input::InputBackend;
|
use backend::input::InputBackend;
|
||||||
|
|
||||||
let mut backend = evt.source.borrow_mut();
|
let mut backend = evt.source.borrow_mut();
|
||||||
if let Err(error) = backend.0.dispatch_new_events() {
|
if let Err(error) = backend.0.dispatch_new_events() {
|
||||||
warn!(backend.0.logger, "Libinput errored: {}", error);
|
warn!(backend.0.logger, "Libinput errored: {}", error);
|
||||||
|
|
|
@ -21,7 +21,7 @@ use udev::{Context, Enumerator, EventType, MonitorBuilder, MonitorSocket, Result
|
||||||
use wayland_server::calloop::{
|
use wayland_server::calloop::{
|
||||||
generic::{EventedFd, Generic},
|
generic::{EventedFd, Generic},
|
||||||
mio::Ready,
|
mio::Ready,
|
||||||
LoopHandle, Source, InsertError,
|
InsertError, LoopHandle, Source,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Backend to monitor available drm devices.
|
/// Backend to monitor available drm devices.
|
||||||
|
@ -48,7 +48,7 @@ impl<T: UdevHandler + 'static> UdevBackend<T> {
|
||||||
/// ## Arguments
|
/// ## Arguments
|
||||||
/// `context` - An initialized udev context
|
/// `context` - An initialized udev context
|
||||||
/// `handler` - User-provided handler to respond to any detected changes
|
/// `handler` - User-provided handler to respond to any detected changes
|
||||||
/// `seat` -
|
/// `seat` -
|
||||||
/// `logger` - slog Logger to be used by the backend and its `DrmDevices`.
|
/// `logger` - slog Logger to be used by the backend and its `DrmDevices`.
|
||||||
pub fn new<L, S: AsRef<str>>(
|
pub fn new<L, S: AsRef<str>>(
|
||||||
context: &Context,
|
context: &Context,
|
||||||
|
@ -66,15 +66,14 @@ impl<T: UdevHandler + 'static> UdevBackend<T> {
|
||||||
// Create devices
|
// Create devices
|
||||||
.flat_map(|path| match stat(&path) {
|
.flat_map(|path| match stat(&path) {
|
||||||
Ok(stat) => {
|
Ok(stat) => {
|
||||||
handler.device_added(stat.st_rdev, path);
|
handler.device_added(stat.st_rdev, path);
|
||||||
Some(stat.st_rdev)
|
Some(stat.st_rdev)
|
||||||
},
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(log, "Unable to get id of {:?}, Error: {:?}. Skipping", path, err);
|
warn!(log, "Unable to get id of {:?}, Error: {:?}. Skipping", path, err);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
}).collect();
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut builder = MonitorBuilder::new(context)?;
|
let mut builder = MonitorBuilder::new(context)?;
|
||||||
builder.match_subsystem("drm")?;
|
builder.match_subsystem("drm")?;
|
||||||
|
@ -89,8 +88,7 @@ impl<T: UdevHandler + 'static> UdevBackend<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: UdevHandler + 'static> Drop for UdevBackend<T>
|
impl<T: UdevHandler + 'static> Drop for UdevBackend<T> {
|
||||||
{
|
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
for device in &self.devices {
|
for device in &self.devices {
|
||||||
self.handler.device_removed(*device);
|
self.handler.device_removed(*device);
|
||||||
|
@ -105,8 +103,7 @@ impl<T: UdevHandler + 'static> Drop for UdevBackend<T>
|
||||||
pub fn udev_backend_bind<T: UdevHandler + 'static, Data: 'static>(
|
pub fn udev_backend_bind<T: UdevHandler + 'static, Data: 'static>(
|
||||||
handle: &LoopHandle<Data>,
|
handle: &LoopHandle<Data>,
|
||||||
udev: UdevBackend<T>,
|
udev: UdevBackend<T>,
|
||||||
) -> Result<Source<Generic<EventedFd<UdevBackend<T>>>>, InsertError<Generic<EventedFd<UdevBackend<T>>>>>
|
) -> Result<Source<Generic<EventedFd<UdevBackend<T>>>>, InsertError<Generic<EventedFd<UdevBackend<T>>>>> {
|
||||||
{
|
|
||||||
let mut source = Generic::from_fd_source(udev);
|
let mut source = Generic::from_fd_source(udev);
|
||||||
source.set_interest(Ready::readable());
|
source.set_interest(Ready::readable());
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
//! Implementation of backend traits for types provided by `winit`
|
//! Implementation of backend traits for types provided by `winit`
|
||||||
|
|
||||||
use backend::{
|
use backend::{
|
||||||
|
egl::{
|
||||||
|
context::GlAttributes, error as egl_error, error::Result as EGLResult, native, EGLContext,
|
||||||
|
EGLDisplay, EGLGraphicsBackend, EGLSurface,
|
||||||
|
},
|
||||||
graphics::{
|
graphics::{
|
||||||
gl::{GLGraphicsBackend, PixelFormat},
|
gl::{GLGraphicsBackend, PixelFormat},
|
||||||
CursorBackend,
|
CursorBackend, SwapBuffersError,
|
||||||
SwapBuffersError,
|
|
||||||
},
|
|
||||||
egl::{
|
|
||||||
context::GlAttributes,
|
|
||||||
error as egl_error,
|
|
||||||
error::Result as EGLResult,
|
|
||||||
native,
|
|
||||||
EGLDisplay, EGLContext, EGLGraphicsBackend, EGLSurface,
|
|
||||||
},
|
},
|
||||||
input::{
|
input::{
|
||||||
Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState, KeyboardKeyEvent,
|
Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState, KeyboardKeyEvent,
|
||||||
|
@ -246,7 +242,8 @@ impl<'a> CursorBackend<'a> for WinitGraphicsBackend {
|
||||||
cursor: Self::CursorFormat,
|
cursor: Self::CursorFormat,
|
||||||
_hotspot: (u32, u32),
|
_hotspot: (u32, u32),
|
||||||
) -> ::std::result::Result<(), ()>
|
) -> ::std::result::Result<(), ()>
|
||||||
where 'a: 'b
|
where
|
||||||
|
'a: 'b,
|
||||||
{
|
{
|
||||||
// Cannot log this one, as `CursorFormat` is not `Debug` and should not be
|
// Cannot log this one, as `CursorFormat` is not `Debug` and should not be
|
||||||
debug!(self.logger, "Changing cursor representation");
|
debug!(self.logger, "Changing cursor representation");
|
||||||
|
|
Loading…
Reference in New Issue