lint: fmt
This commit is contained in:
parent
31b6d84442
commit
9300e35093
|
@ -16,7 +16,10 @@ use smithay::backend::egl::display::EGLBufferReader;
|
|||
use smithay::{
|
||||
backend::{
|
||||
egl::{BufferAccessError, EGLImages, Format},
|
||||
graphics::{gl::GLGraphicsBackend, glium::{GliumGraphicsBackend, Frame}},
|
||||
graphics::{
|
||||
gl::GLGraphicsBackend,
|
||||
glium::{Frame, GliumGraphicsBackend},
|
||||
},
|
||||
},
|
||||
reexports::wayland_server::protocol::{wl_buffer, wl_surface},
|
||||
wayland::{
|
||||
|
@ -159,7 +162,10 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
|
|||
let images = if let Some(display) = &self.egl_buffer_reader.borrow().as_ref() {
|
||||
display.egl_buffer_contents(buffer)
|
||||
} else {
|
||||
Err(BufferAccessError::NotManaged(buffer, smithay::backend::egl::EGLError::BadDisplay))
|
||||
Err(BufferAccessError::NotManaged(
|
||||
buffer,
|
||||
smithay::backend::egl::EGLError::BadDisplay,
|
||||
))
|
||||
};
|
||||
match images {
|
||||
Ok(images) => {
|
||||
|
|
|
@ -319,7 +319,9 @@ impl<S: SessionNotifier, Data: 'static> UdevHandlerImpl<S, Data> {
|
|||
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
|
||||
if let Entry::Vacant(entry) = backends.entry(crtc) {
|
||||
let renderer = GliumDrawer::init(
|
||||
device.create_surface(crtc, connector_info.modes()[0], &[connector_info.handle()]).unwrap(),
|
||||
device
|
||||
.create_surface(crtc, connector_info.modes()[0], &[connector_info.handle()])
|
||||
.unwrap(),
|
||||
egl_buffer_reader.clone(),
|
||||
logger.clone(),
|
||||
);
|
||||
|
|
|
@ -56,7 +56,8 @@ fn main() {
|
|||
let mut options = OpenOptions::new();
|
||||
options.read(true);
|
||||
options.write(true);
|
||||
let mut device = AtomicDrmDevice::new(options.open("/dev/dri/card0").unwrap(), true, log.clone()).unwrap();
|
||||
let mut device =
|
||||
AtomicDrmDevice::new(options.open("/dev/dri/card0").unwrap(), true, log.clone()).unwrap();
|
||||
|
||||
// Get a set of all modesetting resource handles (excluding planes):
|
||||
let res_handles = Device::resource_handles(&device).unwrap();
|
||||
|
@ -96,7 +97,11 @@ fn main() {
|
|||
let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.)
|
||||
|
||||
// Initialize the hardware backend
|
||||
let surface = Rc::new(device.create_surface(crtc, mode, &[connector_info.handle()]).unwrap());
|
||||
let surface = Rc::new(
|
||||
device
|
||||
.create_surface(crtc, mode, &[connector_info.handle()])
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
for conn in surface.current_connectors().into_iter() {
|
||||
if conn != connector_info.handle() {
|
||||
|
|
|
@ -40,7 +40,8 @@ fn main() {
|
|||
let mut options = OpenOptions::new();
|
||||
options.read(true);
|
||||
options.write(true);
|
||||
let mut device = LegacyDrmDevice::new(options.open("/dev/dri/card0").unwrap(), true, log.clone()).unwrap();
|
||||
let mut device =
|
||||
LegacyDrmDevice::new(options.open("/dev/dri/card0").unwrap(), true, log.clone()).unwrap();
|
||||
|
||||
// Get a set of all modesetting resource handles (excluding planes):
|
||||
let res_handles = Device::resource_handles(&device).unwrap();
|
||||
|
@ -78,7 +79,11 @@ fn main() {
|
|||
let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.)
|
||||
|
||||
// Initialize the hardware backend
|
||||
let surface = Rc::new(device.create_surface(crtc, mode, &[connector_info.handle()]).unwrap());
|
||||
let surface = Rc::new(
|
||||
device
|
||||
.create_surface(crtc, mode, &[connector_info.handle()])
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
/*
|
||||
* Lets create buffers and framebuffers.
|
||||
|
|
|
@ -19,7 +19,8 @@ use std::sync::{
|
|||
|
||||
use drm::control::{atomic::AtomicModeReq, AtomicCommitFlags, Device as ControlDevice, Event};
|
||||
use drm::control::{
|
||||
connector, crtc, encoder, framebuffer, plane, property, Mode, PropertyValueSet, ResourceHandle, ResourceHandles,
|
||||
connector, crtc, encoder, framebuffer, plane, property, Mode, PropertyValueSet, ResourceHandle,
|
||||
ResourceHandles,
|
||||
};
|
||||
use drm::SystemError as DrmError;
|
||||
use drm::{ClientCapability, Device as BasicDevice};
|
||||
|
@ -279,25 +280,38 @@ impl<A: AsRawFd + 'static> AtomicDrmDevice<A> {
|
|||
// Disable all connectors as initial state
|
||||
let mut req = AtomicModeReq::new();
|
||||
for conn in res_handles.connectors() {
|
||||
let prop = dev.prop_mapping.0.get(&conn)
|
||||
.expect("Unknown handle").get("CRTC_ID")
|
||||
let prop = dev
|
||||
.prop_mapping
|
||||
.0
|
||||
.get(&conn)
|
||||
.expect("Unknown handle")
|
||||
.get("CRTC_ID")
|
||||
.expect("Unknown property CRTC_ID");
|
||||
req.add_property(*conn, *prop, property::Value::CRTC(None));
|
||||
}
|
||||
// A crtc without a connector has no mode, we also need to reset that.
|
||||
// Otherwise the commit will not be accepted.
|
||||
for crtc in res_handles.crtcs() {
|
||||
let active_prop = dev.prop_mapping.1.get(&crtc)
|
||||
.expect("Unknown handle").get("ACTIVE")
|
||||
let active_prop = dev
|
||||
.prop_mapping
|
||||
.1
|
||||
.get(&crtc)
|
||||
.expect("Unknown handle")
|
||||
.get("ACTIVE")
|
||||
.expect("Unknown property ACTIVE");
|
||||
let mode_prop = dev.prop_mapping.1.get(&crtc)
|
||||
.expect("Unknown handle").get("MODE_ID")
|
||||
let mode_prop = dev
|
||||
.prop_mapping
|
||||
.1
|
||||
.get(&crtc)
|
||||
.expect("Unknown handle")
|
||||
.get("MODE_ID")
|
||||
.expect("Unknown property MODE_ID");
|
||||
req.add_property(*crtc, *mode_prop, property::Value::Unknown(0));
|
||||
req.add_property(*crtc, *active_prop, property::Value::Boolean(false));
|
||||
}
|
||||
dev.atomic_commit(&[AtomicCommitFlags::AllowModeset], req)
|
||||
.compat().map_err(|source| Error::Access {
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to disable connectors",
|
||||
dev: dev.dev_path(),
|
||||
source,
|
||||
|
@ -339,7 +353,12 @@ impl<A: AsRawFd + 'static> Device for AtomicDrmDevice<A> {
|
|||
let _ = self.handler.take();
|
||||
}
|
||||
|
||||
fn create_surface(&mut self, crtc: crtc::Handle, mode: Mode, connectors: &[connector::Handle]) -> Result<AtomicDrmSurface<A>, Error> {
|
||||
fn create_surface(
|
||||
&mut self,
|
||||
crtc: crtc::Handle,
|
||||
mode: Mode,
|
||||
connectors: &[connector::Handle],
|
||||
) -> Result<AtomicDrmSurface<A>, Error> {
|
||||
if self.backends.borrow().contains_key(&crtc) {
|
||||
return Err(Error::CrtcAlreadyInUse(crtc));
|
||||
}
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
//! to an open [`Session`](::backend::session::Session).
|
||||
//!
|
||||
|
||||
use drm::control::{crtc, property, Device as ControlDevice, AtomicCommitFlags, atomic::AtomicModeReq};
|
||||
use drm::control::{atomic::AtomicModeReq, crtc, property, AtomicCommitFlags, Device as ControlDevice};
|
||||
use drm::Device as BasicDevice;
|
||||
use failure::ResultExt;
|
||||
use nix::libc::dev_t;
|
||||
use nix::sys::stat;
|
||||
use std::cell::RefCell;
|
||||
|
@ -13,7 +14,6 @@ use std::os::unix::io::{AsRawFd, RawFd};
|
|||
use std::rc::{Rc, Weak};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use failure::ResultExt;
|
||||
|
||||
use super::{AtomicDrmDevice, AtomicDrmSurfaceInternal, Dev};
|
||||
use crate::backend::drm::{common::Error, DevPath};
|
||||
|
@ -114,31 +114,44 @@ impl<A: AsRawFd + 'static> AtomicDrmDeviceObserver<A> {
|
|||
.map_err(|source| Error::Access {
|
||||
errmsg: "Error loading drm resources",
|
||||
dev: dev.dev_path(),
|
||||
source
|
||||
source,
|
||||
})?;
|
||||
|
||||
// Disable all connectors (otherwise we might run into conflicting commits when restarting the rendering loop)
|
||||
let mut req = AtomicModeReq::new();
|
||||
for conn in res_handles.connectors() {
|
||||
let prop = dev.prop_mapping.0.get(&conn)
|
||||
.expect("Unknown handle").get("CRTC_ID")
|
||||
let prop = dev
|
||||
.prop_mapping
|
||||
.0
|
||||
.get(&conn)
|
||||
.expect("Unknown handle")
|
||||
.get("CRTC_ID")
|
||||
.expect("Unknown property CRTC_ID");
|
||||
req.add_property(*conn, *prop, property::Value::CRTC(None));
|
||||
}
|
||||
// A crtc without a connector has no mode, we also need to reset that.
|
||||
// Otherwise the commit will not be accepted.
|
||||
for crtc in res_handles.crtcs() {
|
||||
let mode_prop = dev.prop_mapping.1.get(&crtc)
|
||||
.expect("Unknown handle").get("MODE_ID")
|
||||
let mode_prop = dev
|
||||
.prop_mapping
|
||||
.1
|
||||
.get(&crtc)
|
||||
.expect("Unknown handle")
|
||||
.get("MODE_ID")
|
||||
.expect("Unknown property MODE_ID");
|
||||
let active_prop = dev.prop_mapping.1.get(&crtc)
|
||||
.expect("Unknown handle").get("ACTIVE")
|
||||
let active_prop = dev
|
||||
.prop_mapping
|
||||
.1
|
||||
.get(&crtc)
|
||||
.expect("Unknown handle")
|
||||
.get("ACTIVE")
|
||||
.expect("Unknown property ACTIVE");
|
||||
req.add_property(*crtc, *active_prop, property::Value::Boolean(false));
|
||||
req.add_property(*crtc, *mode_prop, property::Value::Unknown(0));
|
||||
}
|
||||
dev.atomic_commit(&[AtomicCommitFlags::AllowModeset], req)
|
||||
.compat().map_err(|source| Error::Access {
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to disable connectors",
|
||||
dev: dev.dev_path(),
|
||||
source,
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
use drm::buffer::Buffer;
|
||||
use drm::control::atomic::AtomicModeReq;
|
||||
use drm::control::Device as ControlDevice;
|
||||
use drm::control::{connector, crtc, dumbbuffer::DumbBuffer, framebuffer, plane, property, AtomicCommitFlags, Mode, PlaneType};
|
||||
use drm::control::{
|
||||
connector, crtc, dumbbuffer::DumbBuffer, framebuffer, plane, property, AtomicCommitFlags, Mode, PlaneType,
|
||||
};
|
||||
use drm::Device as BasicDevice;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashSet;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::rc::Rc;
|
||||
use std::sync::{RwLock, atomic::Ordering};
|
||||
use std::sync::{atomic::Ordering, RwLock};
|
||||
|
||||
use failure::ResultExt as FailureResultExt;
|
||||
|
||||
|
@ -57,7 +59,13 @@ impl<A: AsRawFd + 'static> BasicDevice for AtomicDrmSurfaceInternal<A> {}
|
|||
impl<A: AsRawFd + 'static> ControlDevice for AtomicDrmSurfaceInternal<A> {}
|
||||
|
||||
impl<A: AsRawFd + 'static> AtomicDrmSurfaceInternal<A> {
|
||||
pub(crate) fn new(dev: Rc<Dev<A>>, crtc: crtc::Handle, mode: Mode, connectors: &[connector::Handle], logger: ::slog::Logger) -> Result<Self, Error> {
|
||||
pub(crate) fn new(
|
||||
dev: Rc<Dev<A>>,
|
||||
crtc: crtc::Handle,
|
||||
mode: Mode,
|
||||
connectors: &[connector::Handle],
|
||||
logger: ::slog::Logger,
|
||||
) -> Result<Self, Error> {
|
||||
let crtc_info = dev.get_crtc(crtc).compat().map_err(|source| Error::Access {
|
||||
errmsg: "Error loading crtc info",
|
||||
dev: dev.dev_path(),
|
||||
|
@ -70,7 +78,8 @@ impl<A: AsRawFd + 'static> AtomicDrmSurfaceInternal<A> {
|
|||
// So we cheat, because it works and is easier to handle later.
|
||||
let current_mode = crtc_info.mode().unwrap_or_else(|| unsafe { std::mem::zeroed() });
|
||||
let current_blob = match crtc_info.mode() {
|
||||
Some(mode) => dev.create_property_blob(mode)
|
||||
Some(mode) => dev
|
||||
.create_property_blob(mode)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to create Property Blob for mode",
|
||||
|
@ -80,7 +89,8 @@ impl<A: AsRawFd + 'static> AtomicDrmSurfaceInternal<A> {
|
|||
None => property::Value::Unknown(0),
|
||||
};
|
||||
|
||||
let blob = dev.create_property_blob(mode)
|
||||
let blob = dev
|
||||
.create_property_blob(mode)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to create Property Blob for mode",
|
||||
|
@ -96,7 +106,6 @@ impl<A: AsRawFd + 'static> AtomicDrmSurfaceInternal<A> {
|
|||
source,
|
||||
})?;
|
||||
|
||||
|
||||
let mut current_connectors = HashSet::new();
|
||||
for conn in res_handles.connectors() {
|
||||
let crtc_prop = dev
|
||||
|
@ -163,16 +172,22 @@ impl<A: AsRawFd + 'static> AtomicDrmSurfaceInternal<A> {
|
|||
|
||||
fn create_test_buffer(&self, mode: &Mode) -> Result<framebuffer::Handle, Error> {
|
||||
let (w, h) = mode.size();
|
||||
let db = self.create_dumb_buffer((w as u32, h as u32), drm::buffer::format::PixelFormat::ARGB8888).compat().map_err(|source| Error::Access {
|
||||
errmsg: "Failed to create dumb buffer",
|
||||
dev: self.dev_path(),
|
||||
source
|
||||
})?;
|
||||
let fb = self.add_framebuffer(&db).compat().map_err(|source| Error::Access {
|
||||
errmsg: "Failed to create framebuffer",
|
||||
dev: self.dev_path(),
|
||||
source
|
||||
})?;
|
||||
let db = self
|
||||
.create_dumb_buffer((w as u32, h as u32), drm::buffer::format::PixelFormat::ARGB8888)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to create dumb buffer",
|
||||
dev: self.dev_path(),
|
||||
source,
|
||||
})?;
|
||||
let fb = self
|
||||
.add_framebuffer(&db)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to create framebuffer",
|
||||
dev: self.dev_path(),
|
||||
source,
|
||||
})?;
|
||||
if let Some((old_db, old_fb)) = self.test_buffer.replace(Some((db, fb))) {
|
||||
let _ = self.destroy_framebuffer(old_fb);
|
||||
let _ = self.destroy_dumb_buffer(old_db);
|
||||
|
@ -210,17 +225,32 @@ impl<A: AsRawFd + 'static> Drop for AtomicDrmSurfaceInternal<A> {
|
|||
let current = self.state.read().unwrap();
|
||||
let mut req = AtomicModeReq::new();
|
||||
for conn in current.connectors.iter() {
|
||||
let prop = self.dev.prop_mapping.0.get(&conn)
|
||||
.expect("Unknown Handle").get("CRTC_ID")
|
||||
let prop = self
|
||||
.dev
|
||||
.prop_mapping
|
||||
.0
|
||||
.get(&conn)
|
||||
.expect("Unknown Handle")
|
||||
.get("CRTC_ID")
|
||||
.expect("Unknown property CRTC_ID");
|
||||
req.add_property(*conn, *prop, property::Value::CRTC(None));
|
||||
}
|
||||
let active_prop = self.dev.prop_mapping.1.get(&self.crtc)
|
||||
.expect("Unknown Handle").get("ACTIVE")
|
||||
.expect("Unknown property ACTIVE");
|
||||
let mode_prop = self.dev.prop_mapping.1.get(&self.crtc)
|
||||
.expect("Unknown Handle").get("MODE_ID")
|
||||
.expect("Unknown property MODE_ID");
|
||||
let active_prop = self
|
||||
.dev
|
||||
.prop_mapping
|
||||
.1
|
||||
.get(&self.crtc)
|
||||
.expect("Unknown Handle")
|
||||
.get("ACTIVE")
|
||||
.expect("Unknown property ACTIVE");
|
||||
let mode_prop = self
|
||||
.dev
|
||||
.prop_mapping
|
||||
.1
|
||||
.get(&self.crtc)
|
||||
.expect("Unknown Handle")
|
||||
.get("MODE_ID")
|
||||
.expect("Unknown property MODE_ID");
|
||||
|
||||
req.add_property(self.crtc, *active_prop, property::Value::Boolean(false));
|
||||
req.add_property(self.crtc, *mode_prop, property::Value::Unknown(0));
|
||||
|
@ -376,13 +406,13 @@ impl<A: AsRawFd + 'static> Surface for AtomicDrmSurfaceInternal<A> {
|
|||
|
||||
// check if new config is supported
|
||||
let new_blob = self
|
||||
.create_property_blob(mode)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to create Property Blob for mode",
|
||||
dev: self.dev_path(),
|
||||
source,
|
||||
})?;
|
||||
.create_property_blob(mode)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to create Property Blob for mode",
|
||||
dev: self.dev_path(),
|
||||
source,
|
||||
})?;
|
||||
|
||||
let test_fb = Some(self.create_test_buffer(&pending.mode)?);
|
||||
let req = self.build_request(
|
||||
|
@ -453,11 +483,7 @@ impl<A: AsRawFd + 'static> RawSurface for AtomicDrmSurfaceInternal<A> {
|
|||
}
|
||||
|
||||
if current.mode != pending.mode {
|
||||
info!(
|
||||
self.logger,
|
||||
"Setting new mode: {:?}",
|
||||
pending.mode.name()
|
||||
);
|
||||
info!(self.logger, "Setting new mode: {:?}", pending.mode.name());
|
||||
}
|
||||
|
||||
trace!(self.logger, "Testing screen config");
|
||||
|
@ -533,25 +559,25 @@ impl<A: AsRawFd + 'static> RawSurface for AtomicDrmSurfaceInternal<A> {
|
|||
return Err(Error::DeviceInactive);
|
||||
}
|
||||
|
||||
let req = self
|
||||
.build_request(
|
||||
&mut [].iter(),
|
||||
&mut [].iter(),
|
||||
&self.planes,
|
||||
Some(framebuffer),
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
let req = self.build_request(
|
||||
&mut [].iter(),
|
||||
&mut [].iter(),
|
||||
&self.planes,
|
||||
Some(framebuffer),
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
|
||||
trace!(self.logger, "Queueing page flip: {:#?}", req);
|
||||
self.atomic_commit(
|
||||
&[AtomicCommitFlags::PageFlipEvent, AtomicCommitFlags::Nonblock],
|
||||
req,
|
||||
)
|
||||
.compat().map_err(|source| Error::Access {
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Page flip commit failed",
|
||||
dev: self.dev_path(),
|
||||
source
|
||||
source,
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -22,8 +22,8 @@ use drm::{
|
|||
#[cfg(feature = "renderer_gl")]
|
||||
use nix::libc::c_void;
|
||||
use nix::libc::dev_t;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::env;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
#[cfg(feature = "use_system_lib")]
|
||||
use wayland_server::Display;
|
||||
|
||||
|
@ -175,15 +175,17 @@ impl<A: AsRawFd + Clone + 'static> FallbackDevice<AtomicDrmDevice<A>, LegacyDrmD
|
|||
info!(log, "Trying to initialize AtomicDrmDevice");
|
||||
|
||||
if env::var("SMITHAY_USE_LEGACY")
|
||||
.map(|x|
|
||||
x == "1"
|
||||
|| x.to_lowercase() == "true"
|
||||
|| x.to_lowercase() == "yes"
|
||||
|| x.to_lowercase() == "y"
|
||||
).unwrap_or(false)
|
||||
.map(|x| {
|
||||
x == "1" || x.to_lowercase() == "true" || x.to_lowercase() == "yes" || x.to_lowercase() == "y"
|
||||
})
|
||||
.unwrap_or(false)
|
||||
{
|
||||
info!(log, "SMITHAY_USE_LEGACY is set. Forcing LegacyDrmDevice.");
|
||||
return Ok(FallbackDevice::Fallback(LegacyDrmDevice::new(fd, disable_connectors, log)?));
|
||||
return Ok(FallbackDevice::Fallback(LegacyDrmDevice::new(
|
||||
fd,
|
||||
disable_connectors,
|
||||
log,
|
||||
)?));
|
||||
}
|
||||
|
||||
match AtomicDrmDevice::new(fd.clone(), disable_connectors, log.clone()) {
|
||||
|
@ -191,7 +193,11 @@ impl<A: AsRawFd + Clone + 'static> FallbackDevice<AtomicDrmDevice<A>, LegacyDrmD
|
|||
Err(err) => {
|
||||
error!(log, "Failed to initialize preferred AtomicDrmDevice: {}", err);
|
||||
info!(log, "Falling back to fallback LegacyDrmDevice");
|
||||
Ok(FallbackDevice::Fallback(LegacyDrmDevice::new(fd, disable_connectors, log)?))
|
||||
Ok(FallbackDevice::Fallback(LegacyDrmDevice::new(
|
||||
fd,
|
||||
disable_connectors,
|
||||
log,
|
||||
)?))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,10 +263,19 @@ where
|
|||
}
|
||||
}
|
||||
fallback_device_impl!(clear_handler, &mut Self);
|
||||
fn create_surface(&mut self, crtc: crtc::Handle, mode: Mode, connectors: &[connector::Handle]) -> Result<Self::Surface, E> {
|
||||
fn create_surface(
|
||||
&mut self,
|
||||
crtc: crtc::Handle,
|
||||
mode: Mode,
|
||||
connectors: &[connector::Handle],
|
||||
) -> Result<Self::Surface, E> {
|
||||
match self {
|
||||
FallbackDevice::Preference(dev) => Ok(FallbackSurface::Preference(dev.create_surface(crtc, mode, connectors)?)),
|
||||
FallbackDevice::Fallback(dev) => Ok(FallbackSurface::Fallback(dev.create_surface(crtc, mode, connectors)?)),
|
||||
FallbackDevice::Preference(dev) => Ok(FallbackSurface::Preference(
|
||||
dev.create_surface(crtc, mode, connectors)?,
|
||||
)),
|
||||
FallbackDevice::Fallback(dev) => Ok(FallbackSurface::Fallback(
|
||||
dev.create_surface(crtc, mode, connectors)?,
|
||||
)),
|
||||
}
|
||||
}
|
||||
fallback_device_impl!(process_events, &mut Self);
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
//! and [`Surface`](::backend::drm::Surface) implementations of the `backend::drm` module.
|
||||
//!
|
||||
|
||||
use crate::backend::graphics::SwapBuffersError;
|
||||
use drm::control::{connector, crtc, Mode, RawResourceHandle};
|
||||
use std::path::PathBuf;
|
||||
use crate::backend::graphics::SwapBuffersError;
|
||||
|
||||
pub mod fallback;
|
||||
|
||||
|
@ -81,10 +81,17 @@ impl Into<SwapBuffersError> for Error {
|
|||
dev: _,
|
||||
source,
|
||||
} if match source.get_ref() {
|
||||
drm::SystemError::Unknown { errno: nix::errno::Errno::EBUSY } => true,
|
||||
drm::SystemError::Unknown { errno: nix::errno::Errno::EINTR } => true,
|
||||
drm::SystemError::Unknown {
|
||||
errno: nix::errno::Errno::EBUSY,
|
||||
} => true,
|
||||
drm::SystemError::Unknown {
|
||||
errno: nix::errno::Errno::EINTR,
|
||||
} => true,
|
||||
_ => false,
|
||||
} => SwapBuffersError::TemporaryFailure(Box::new(source)),
|
||||
} =>
|
||||
{
|
||||
SwapBuffersError::TemporaryFailure(Box::new(source))
|
||||
}
|
||||
x => SwapBuffersError::ContextLost(Box::new(x)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@ use wayland_server::Display;
|
|||
|
||||
use super::{Device, DeviceHandler, Surface};
|
||||
use crate::backend::egl::native::{Backend, NativeDisplay, NativeSurface};
|
||||
use crate::backend::egl::{Error as EGLError, EGLError as RawEGLError, SurfaceCreationError};
|
||||
#[cfg(feature = "use_system_lib")]
|
||||
use crate::backend::egl::{display::EGLBufferReader, EGLGraphicsBackend};
|
||||
use crate::backend::egl::{EGLError as RawEGLError, Error as EGLError, SurfaceCreationError};
|
||||
|
||||
mod surface;
|
||||
pub use self::surface::*;
|
||||
|
@ -49,7 +49,9 @@ type Arguments = (crtc::Handle, Mode, Vec<connector::Handle>);
|
|||
pub struct EglDevice<B, D>
|
||||
where
|
||||
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||
D: Device + NativeDisplay<B, Arguments = Arguments, Error=<<D as Device>::Surface as Surface>::Error> + 'static,
|
||||
D: Device
|
||||
+ NativeDisplay<B, Arguments = Arguments, Error = <<D as Device>::Surface as Surface>::Error>
|
||||
+ 'static,
|
||||
<D as Device>::Surface: NativeSurface,
|
||||
{
|
||||
dev: EGLDisplay<B, D>,
|
||||
|
@ -61,7 +63,9 @@ where
|
|||
impl<B, D> AsRawFd for EglDevice<B, D>
|
||||
where
|
||||
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||
D: Device + NativeDisplay<B, Arguments = Arguments, Error=<<D as Device>::Surface as Surface>::Error> + 'static,
|
||||
D: Device
|
||||
+ NativeDisplay<B, Arguments = Arguments, Error = <<D as Device>::Surface as Surface>::Error>
|
||||
+ 'static,
|
||||
<D as Device>::Surface: NativeSurface,
|
||||
{
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
|
@ -72,7 +76,9 @@ where
|
|||
impl<B, D> EglDevice<B, D>
|
||||
where
|
||||
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||
D: Device + NativeDisplay<B, Arguments = Arguments, Error=<<D as Device>::Surface as Surface>::Error> + 'static,
|
||||
D: Device
|
||||
+ NativeDisplay<B, Arguments = Arguments, Error = <<D as Device>::Surface as Surface>::Error>
|
||||
+ 'static,
|
||||
<D as Device>::Surface: NativeSurface,
|
||||
{
|
||||
/// Try to create a new [`EglDevice`] from an open device.
|
||||
|
@ -127,7 +133,9 @@ where
|
|||
struct InternalDeviceHandler<B, D>
|
||||
where
|
||||
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||
D: Device + NativeDisplay<B, Arguments = Arguments, Error=<<D as Device>::Surface as Surface>::Error> + 'static,
|
||||
D: Device
|
||||
+ NativeDisplay<B, Arguments = Arguments, Error = <<D as Device>::Surface as Surface>::Error>
|
||||
+ 'static,
|
||||
<D as Device>::Surface: NativeSurface,
|
||||
{
|
||||
handler: Box<dyn DeviceHandler<Device = EglDevice<B, D>> + 'static>,
|
||||
|
@ -136,7 +144,9 @@ where
|
|||
impl<B, D> DeviceHandler for InternalDeviceHandler<B, D>
|
||||
where
|
||||
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||
D: Device + NativeDisplay<B, Arguments = Arguments, Error=<<D as Device>::Surface as Surface>::Error> + 'static,
|
||||
D: Device
|
||||
+ NativeDisplay<B, Arguments = Arguments, Error = <<D as Device>::Surface as Surface>::Error>
|
||||
+ 'static,
|
||||
<D as Device>::Surface: NativeSurface,
|
||||
{
|
||||
type Device = D;
|
||||
|
@ -152,7 +162,9 @@ where
|
|||
impl<B, D> Device for EglDevice<B, D>
|
||||
where
|
||||
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||
D: Device + NativeDisplay<B, Arguments = Arguments, Error=<<D as Device>::Surface as Surface>::Error> + 'static,
|
||||
D: Device
|
||||
+ NativeDisplay<B, Arguments = Arguments, Error = <<D as Device>::Surface as Surface>::Error>
|
||||
+ 'static,
|
||||
<D as Device>::Surface: NativeSurface,
|
||||
{
|
||||
type Surface = EglSurface<<D as Device>::Surface>;
|
||||
|
@ -231,7 +243,9 @@ where
|
|||
impl<B, D> EGLGraphicsBackend for EglDevice<B, D>
|
||||
where
|
||||
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||
D: Device + NativeDisplay<B, Arguments = Arguments, Error=<<D as Device>::Surface as Surface>::Error> + 'static,
|
||||
D: Device
|
||||
+ NativeDisplay<B, Arguments = Arguments, Error = <<D as Device>::Surface as Surface>::Error>
|
||||
+ 'static,
|
||||
<D as Device>::Surface: NativeSurface,
|
||||
{
|
||||
fn bind_wl_display(&self, display: &Display) -> Result<EGLBufferReader, EGLError> {
|
||||
|
@ -242,7 +256,9 @@ where
|
|||
impl<B, D> Drop for EglDevice<B, D>
|
||||
where
|
||||
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||
D: Device + NativeDisplay<B, Arguments = Arguments, Error=<<D as Device>::Surface as Surface>::Error> + 'static,
|
||||
D: Device
|
||||
+ NativeDisplay<B, Arguments = Arguments, Error = <<D as Device>::Surface as Surface>::Error>
|
||||
+ 'static,
|
||||
<D as Device>::Surface: NativeSurface,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//! to an open [`Session`](::backend::session::Session).
|
||||
//!
|
||||
|
||||
use drm::control::{crtc, connector, Mode};
|
||||
use drm::control::{connector, crtc, Mode};
|
||||
use std::os::unix::io::RawFd;
|
||||
|
||||
use super::EglDevice;
|
||||
|
@ -22,7 +22,13 @@ impl<S, B, D> AsSessionObserver<EglDeviceObserver<S>> for EglDevice<B, D>
|
|||
where
|
||||
S: SessionObserver + 'static,
|
||||
B: Backend<Surface = <D as Device>::Surface> + 'static,
|
||||
D: Device + NativeDisplay<B, Arguments = (crtc::Handle, Mode, Vec<connector::Handle>), Error=<<D as Device>::Surface as Surface>::Error> + AsSessionObserver<S> + 'static,
|
||||
D: Device
|
||||
+ NativeDisplay<
|
||||
B,
|
||||
Arguments = (crtc::Handle, Mode, Vec<connector::Handle>),
|
||||
Error = <<D as Device>::Surface as Surface>::Error,
|
||||
> + AsSessionObserver<S>
|
||||
+ 'static,
|
||||
<D as Device>::Surface: NativeSurface,
|
||||
{
|
||||
fn observer(&mut self) -> EglDeviceObserver<S> {
|
||||
|
|
|
@ -99,7 +99,9 @@ where
|
|||
Ok(x) => x,
|
||||
Err(x) => x.into(),
|
||||
})
|
||||
} else { Ok(()) }
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_proc_address(&self, symbol: &str) -> *const c_void {
|
||||
|
@ -116,7 +118,9 @@ where
|
|||
}
|
||||
|
||||
unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError> {
|
||||
self.context.make_current_with_surface(&self.surface).map_err(Into::into)
|
||||
self.context
|
||||
.make_current_with_surface(&self.surface)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn get_pixel_format(&self) -> PixelFormat {
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
use crate::backend::drm::{Device, RawDevice, Surface};
|
||||
use crate::backend::egl::ffi;
|
||||
use crate::backend::egl::native::{Backend, NativeDisplay, NativeSurface};
|
||||
use crate::backend::egl::{Error as EglBackendError, EGLError, wrap_egl_call};
|
||||
use crate::backend::egl::{wrap_egl_call, EGLError, Error as EglBackendError};
|
||||
|
||||
use super::{Error, GbmDevice, GbmSurface};
|
||||
|
||||
use drm::control::{crtc, connector, Device as ControlDevice, Mode};
|
||||
use drm::control::{connector, crtc, Device as ControlDevice, Mode};
|
||||
use gbm::AsRaw;
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
|
@ -36,13 +36,19 @@ impl<D: RawDevice + 'static> Backend for Gbm<D> {
|
|||
{
|
||||
if has_dp_extension("EGL_KHR_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
|
||||
trace!(log, "EGL Display Initialization via EGL_KHR_platform_gbm");
|
||||
wrap_egl_call(|| ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null()))
|
||||
wrap_egl_call(|| {
|
||||
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null())
|
||||
})
|
||||
} else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplayEXT::is_loaded() {
|
||||
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
|
||||
wrap_egl_call(|| ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null()))
|
||||
wrap_egl_call(|| {
|
||||
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null())
|
||||
})
|
||||
} else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
|
||||
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
|
||||
wrap_egl_call(|| ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null()))
|
||||
wrap_egl_call(|| {
|
||||
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null())
|
||||
})
|
||||
} else {
|
||||
trace!(log, "Default EGL Display Initialization via GetDisplay");
|
||||
wrap_egl_call(|| ffi::egl::GetDisplay(display as *mut _))
|
||||
|
|
|
@ -171,13 +171,11 @@ impl<D: RawDevice + ControlDevice + 'static> Device for GbmDevice<D> {
|
|||
) -> Result<GbmSurface<D>, Error<<<D as Device>::Surface as Surface>::Error>> {
|
||||
info!(self.logger, "Initializing GbmSurface");
|
||||
|
||||
let drm_surface =
|
||||
Device::create_surface(&mut **self.dev.borrow_mut(), crtc, mode, connectors).map_err(Error::Underlying)?;
|
||||
let drm_surface = Device::create_surface(&mut **self.dev.borrow_mut(), crtc, mode, connectors)
|
||||
.map_err(Error::Underlying)?;
|
||||
|
||||
// initialize the surface
|
||||
let (w, h) = drm_surface
|
||||
.pending_mode()
|
||||
.size();
|
||||
let (w, h) = drm_surface.pending_mode().size();
|
||||
let surface = self
|
||||
.dev
|
||||
.borrow()
|
||||
|
@ -260,16 +258,24 @@ impl<D: RawDevice + ControlDevice + 'static> Drop for GbmDevice<D> {
|
|||
|
||||
impl<E> Into<SwapBuffersError> for Error<E>
|
||||
where
|
||||
E: std::error::Error + Into<SwapBuffersError> + 'static
|
||||
E: std::error::Error + Into<SwapBuffersError> + 'static,
|
||||
{
|
||||
fn into(self) -> SwapBuffersError {
|
||||
match self {
|
||||
Error::FrontBuffersExhausted => SwapBuffersError::AlreadySwapped,
|
||||
Error::FramebufferCreationFailed(x) if match x.get_ref() {
|
||||
&drm::SystemError::Unknown { errno: nix::errno::Errno::EBUSY } => true,
|
||||
&drm::SystemError::Unknown { errno: nix::errno::Errno::EINTR } => true,
|
||||
_ => false
|
||||
} => SwapBuffersError::TemporaryFailure(Box::new(x)),
|
||||
Error::FramebufferCreationFailed(x)
|
||||
if match x.get_ref() {
|
||||
&drm::SystemError::Unknown {
|
||||
errno: nix::errno::Errno::EBUSY,
|
||||
} => true,
|
||||
&drm::SystemError::Unknown {
|
||||
errno: nix::errno::Errno::EINTR,
|
||||
} => true,
|
||||
_ => false,
|
||||
} =>
|
||||
{
|
||||
SwapBuffersError::TemporaryFailure(Box::new(x))
|
||||
}
|
||||
Error::Underlying(x) => x.into(),
|
||||
x => SwapBuffersError::ContextLost(Box::new(x)),
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ pub struct GbmDeviceObserver<
|
|||
|
||||
impl<
|
||||
O: SessionObserver + 'static,
|
||||
S: CursorBackend<CursorFormat=dyn drm::buffer::Buffer> + RawSurface + 'static,
|
||||
D: RawDevice<Surface=S> + drm::control::Device + AsSessionObserver<O> + 'static,
|
||||
S: CursorBackend<CursorFormat = dyn drm::buffer::Buffer> + RawSurface + 'static,
|
||||
D: RawDevice<Surface = S> + drm::control::Device + AsSessionObserver<O> + 'static,
|
||||
> AsSessionObserver<GbmDeviceObserver<O, D>> for GbmDevice<D>
|
||||
{
|
||||
fn observer(&mut self) -> GbmDeviceObserver<O, D> {
|
||||
|
@ -44,8 +44,8 @@ impl<
|
|||
|
||||
impl<
|
||||
O: SessionObserver + 'static,
|
||||
S: CursorBackend<CursorFormat=dyn drm::buffer::Buffer> + RawSurface + 'static,
|
||||
D: RawDevice<Surface=S> + drm::control::Device + AsSessionObserver<O> + 'static,
|
||||
S: CursorBackend<CursorFormat = dyn drm::buffer::Buffer> + RawSurface + 'static,
|
||||
D: RawDevice<Surface = S> + drm::control::Device + AsSessionObserver<O> + 'static,
|
||||
> SessionObserver for GbmDeviceObserver<O, D>
|
||||
{
|
||||
fn pause(&mut self, devnum: Option<(u32, u32)>) {
|
||||
|
@ -81,9 +81,7 @@ impl<
|
|||
|
||||
let &(ref cursor, ref hotspot): &(BufferObject<()>, (u32, u32)) =
|
||||
unsafe { &*backend.cursor.as_ptr() };
|
||||
if backend.crtc.set_cursor_representation(cursor, *hotspot)
|
||||
.is_err()
|
||||
{
|
||||
if backend.crtc.set_cursor_representation(cursor, *hotspot).is_err() {
|
||||
if let Err(err) = backend.dev.borrow().set_cursor(*crtc, Some(cursor)) {
|
||||
error!(self.logger, "Failed to reset cursor. Error: {}", err);
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ use super::super::{Device, RawDevice, RawSurface, Surface};
|
|||
use super::Error;
|
||||
|
||||
use drm::control::{connector, crtc, framebuffer, Device as ControlDevice, Mode};
|
||||
use failure::ResultExt;
|
||||
use gbm::{self, BufferObject, BufferObjectFlags, Format as GbmFormat, SurfaceBufferHandle};
|
||||
use image::{ImageBuffer, Rgba};
|
||||
use failure::ResultExt;
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::rc::Rc;
|
||||
|
@ -89,9 +89,7 @@ impl<D: RawDevice + 'static> GbmSurfaceInternal<D> {
|
|||
}
|
||||
|
||||
pub fn recreate(&self) -> Result<(), Error<<<D as Device>::Surface as Surface>::Error>> {
|
||||
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
|
||||
// resolution.
|
||||
|
|
|
@ -190,33 +190,55 @@ impl<A: AsRawFd + 'static> LegacyDrmDevice<A> {
|
|||
}
|
||||
|
||||
impl<A: AsRawFd + 'static> Dev<A> {
|
||||
pub(in crate::backend::drm::legacy) fn set_connector_state(&self, connectors: impl Iterator<Item=connector::Handle>, enabled: bool) -> Result<(), Error> {
|
||||
pub(in crate::backend::drm::legacy) fn set_connector_state(
|
||||
&self,
|
||||
connectors: impl Iterator<Item = connector::Handle>,
|
||||
enabled: bool,
|
||||
) -> Result<(), Error> {
|
||||
for conn in connectors {
|
||||
let info = self.get_connector(conn).compat().map_err(|source| Error::Access {
|
||||
let info = self
|
||||
.get_connector(conn)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to get connector infos",
|
||||
dev: self.dev_path(),
|
||||
source
|
||||
source,
|
||||
})?;
|
||||
if info.state() == connector::State::Connected {
|
||||
let props = self.get_properties(conn).compat().map_err(|source| Error::Access {
|
||||
errmsg: "Failed to get properties for connector",
|
||||
dev: self.dev_path(),
|
||||
source
|
||||
})?;
|
||||
let props = self
|
||||
.get_properties(conn)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to get properties for connector",
|
||||
dev: self.dev_path(),
|
||||
source,
|
||||
})?;
|
||||
let (handles, _) = props.as_props_and_values();
|
||||
for handle in handles {
|
||||
let info = self.get_property(*handle).compat().map_err(|source| Error::Access {
|
||||
errmsg: "Failed to get property of connector",
|
||||
dev: self.dev_path(),
|
||||
source
|
||||
})?;
|
||||
let info = self
|
||||
.get_property(*handle)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to get property of connector",
|
||||
dev: self.dev_path(),
|
||||
source,
|
||||
})?;
|
||||
if info.name().to_str().map(|x| x == "DPMS").unwrap_or(false) {
|
||||
self.set_property(conn, *handle, if enabled { 0 /*DRM_MODE_DPMS_ON*/} else { 3 /*DRM_MODE_DPMS_OFF*/})
|
||||
.compat().map_err(|source| Error::Access {
|
||||
errmsg: "Failed to set property of connector",
|
||||
dev: self.dev_path(),
|
||||
source
|
||||
})?;
|
||||
self.set_property(
|
||||
conn,
|
||||
*handle,
|
||||
if enabled {
|
||||
0 /*DRM_MODE_DPMS_ON*/
|
||||
} else {
|
||||
3 /*DRM_MODE_DPMS_OFF*/
|
||||
},
|
||||
)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to set property of connector",
|
||||
dev: self.dev_path(),
|
||||
source,
|
||||
})?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -249,7 +271,12 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
|
|||
let _ = self.handler.take();
|
||||
}
|
||||
|
||||
fn create_surface(&mut self, crtc: crtc::Handle, mode: Mode, connectors: &[connector::Handle]) -> Result<LegacyDrmSurface<A>, Error> {
|
||||
fn create_surface(
|
||||
&mut self,
|
||||
crtc: crtc::Handle,
|
||||
mode: Mode,
|
||||
connectors: &[connector::Handle],
|
||||
) -> Result<LegacyDrmSurface<A>, Error> {
|
||||
if self.backends.borrow().contains_key(&crtc) {
|
||||
return Err(Error::CrtcAlreadyInUse(crtc));
|
||||
}
|
||||
|
@ -263,7 +290,10 @@ impl<A: AsRawFd + 'static> Device for LegacyDrmDevice<A> {
|
|||
}
|
||||
|
||||
let backend = Rc::new(LegacyDrmSurfaceInternal::new(
|
||||
self.dev.clone(), crtc, mode, connectors,
|
||||
self.dev.clone(),
|
||||
crtc,
|
||||
mode,
|
||||
connectors,
|
||||
self.logger.new(o!("crtc" => format!("{:?}", crtc))),
|
||||
)?);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
use drm::control::{crtc, Device as ControlDevice};
|
||||
use drm::Device as BasicDevice;
|
||||
use failure::ResultExt;
|
||||
use nix::libc::dev_t;
|
||||
use nix::sys::stat;
|
||||
use std::cell::RefCell;
|
||||
|
@ -13,9 +14,8 @@ use std::os::unix::io::{AsRawFd, RawFd};
|
|||
use std::rc::{Rc, Weak};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use failure::ResultExt;
|
||||
|
||||
use super::{Dev, LegacyDrmDevice, LegacyDrmSurfaceInternal, Error, DevPath};
|
||||
use super::{Dev, DevPath, Error, LegacyDrmDevice, LegacyDrmSurfaceInternal};
|
||||
use crate::backend::session::{AsSessionObserver, SessionObserver};
|
||||
|
||||
/// [`SessionObserver`](SessionObserver)
|
||||
|
@ -125,11 +125,14 @@ impl<A: AsRawFd + 'static> LegacyDrmDeviceObserver<A> {
|
|||
// set current connectors
|
||||
current.connectors.clear();
|
||||
for conn in res_handles.connectors() {
|
||||
let conn_info = dev.get_connector(*conn).compat().map_err(|source| Error::Access {
|
||||
errmsg: "Could not load connector info",
|
||||
dev: dev.dev_path(),
|
||||
source,
|
||||
})?;
|
||||
let conn_info =
|
||||
dev.get_connector(*conn)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Could not load connector info",
|
||||
dev: dev.dev_path(),
|
||||
source,
|
||||
})?;
|
||||
if let Some(enc) = conn_info.current_encoder() {
|
||||
let enc_info = dev.get_encoder(enc).compat().map_err(|source| Error::Access {
|
||||
errmsg: "Could not load encoder info",
|
||||
|
@ -143,11 +146,14 @@ impl<A: AsRawFd + 'static> LegacyDrmDeviceObserver<A> {
|
|||
}
|
||||
|
||||
// set current mode
|
||||
let crtc_info = dev.get_crtc(surface.crtc).compat().map_err(|source| Error::Access {
|
||||
errmsg: "Could not load crtc info",
|
||||
dev: dev.dev_path(),
|
||||
source,
|
||||
})?;
|
||||
let crtc_info = dev
|
||||
.get_crtc(surface.crtc)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Could not load crtc info",
|
||||
dev: dev.dev_path(),
|
||||
source,
|
||||
})?;
|
||||
|
||||
// If we have no current mode, we create a fake one, which will not match (and thus gets overriden on the commit below).
|
||||
// A better fix would probably be making mode an `Option`, but that would mean
|
||||
|
|
|
@ -8,7 +8,7 @@ use drm::Device as BasicDevice;
|
|||
use std::collections::HashSet;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::rc::Rc;
|
||||
use std::sync::{RwLock, atomic::Ordering};
|
||||
use std::sync::{atomic::Ordering, RwLock};
|
||||
|
||||
use crate::backend::drm::{common::Error, DevPath, RawSurface, Surface};
|
||||
use crate::backend::graphics::CursorBackend;
|
||||
|
@ -241,11 +241,7 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
|
|||
self.dev.set_connector_state(added.copied(), true)?;
|
||||
|
||||
if current.mode != pending.mode {
|
||||
info!(
|
||||
self.logger,
|
||||
"Setting new mode: {:?}",
|
||||
pending.mode.name()
|
||||
);
|
||||
info!(self.logger, "Setting new mode: {:?}", pending.mode.name());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,7 +293,8 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
|
|||
framebuffer,
|
||||
&[PageFlipFlags::PageFlipEvent],
|
||||
None,
|
||||
).compat()
|
||||
)
|
||||
.compat()
|
||||
.map_err(|source| Error::Access {
|
||||
errmsg: "Failed to page flip",
|
||||
dev: self.dev_path(),
|
||||
|
@ -307,7 +304,13 @@ impl<A: AsRawFd + 'static> RawSurface for LegacyDrmSurfaceInternal<A> {
|
|||
}
|
||||
|
||||
impl<A: AsRawFd + 'static> LegacyDrmSurfaceInternal<A> {
|
||||
pub(crate) fn new(dev: Rc<Dev<A>>, crtc: crtc::Handle, mode: Mode, connectors: &[connector::Handle], logger: ::slog::Logger) -> Result<LegacyDrmSurfaceInternal<A>, Error> {
|
||||
pub(crate) fn new(
|
||||
dev: Rc<Dev<A>>,
|
||||
crtc: crtc::Handle,
|
||||
mode: Mode,
|
||||
connectors: &[connector::Handle],
|
||||
logger: ::slog::Logger,
|
||||
) -> Result<LegacyDrmSurfaceInternal<A>, Error> {
|
||||
// Try to enumarate the current state to set the initial state variable correctly
|
||||
let crtc_info = dev.get_crtc(crtc).compat().map_err(|source| Error::Access {
|
||||
errmsg: "Error loading crtc info",
|
||||
|
@ -349,8 +352,14 @@ impl<A: AsRawFd + 'static> LegacyDrmSurfaceInternal<A> {
|
|||
// A better fix would probably be making mode an `Option`, but that would mean
|
||||
// we need to be sure, we require a mode to always be set without relying on the compiler.
|
||||
// So we cheat, because it works and is easier to handle later.
|
||||
let state = State { mode: current_mode.unwrap_or_else(|| unsafe { std::mem::zeroed() }), connectors: current_connectors };
|
||||
let pending = State { mode, connectors: connectors.into_iter().copied().collect() };
|
||||
let state = State {
|
||||
mode: current_mode.unwrap_or_else(|| unsafe { std::mem::zeroed() }),
|
||||
connectors: current_connectors,
|
||||
};
|
||||
let pending = State {
|
||||
mode,
|
||||
connectors: connectors.into_iter().copied().collect(),
|
||||
};
|
||||
|
||||
let surface = LegacyDrmSurfaceInternal {
|
||||
dev,
|
||||
|
@ -428,7 +437,10 @@ impl<A: AsRawFd + 'static> Drop for LegacyDrmSurfaceInternal<A> {
|
|||
let _ = self.set_cursor(self.crtc, Option::<&DumbBuffer>::None);
|
||||
// disable connectors again
|
||||
let current = self.state.read().unwrap();
|
||||
if let Ok(_) = self.dev.set_connector_state(current.connectors.iter().copied(), false) {
|
||||
if let Ok(_) = self
|
||||
.dev
|
||||
.set_connector_state(current.connectors.iter().copied(), false)
|
||||
{
|
||||
// null commit
|
||||
let _ = self.set_crtc(self.crtc, None, (0, 0), &[], None);
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ pub trait Device: AsRawFd + DevPath {
|
|||
&mut self,
|
||||
crtc: crtc::Handle,
|
||||
mode: Mode,
|
||||
connectors: &[connector::Handle]
|
||||
connectors: &[connector::Handle],
|
||||
) -> Result<Self::Surface, <Self::Surface as Surface>::Error>;
|
||||
|
||||
/// Processes any open events of the underlying file descriptor.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! EGL context related structs
|
||||
|
||||
use super::{ffi, Error, MakeCurrentError, wrap_egl_call};
|
||||
use super::{ffi, wrap_egl_call, Error, MakeCurrentError};
|
||||
use crate::backend::egl::display::{EGLDisplay, EGLDisplayHandle};
|
||||
use crate::backend::egl::native::NativeSurface;
|
||||
use crate::backend::egl::{native, EGLSurface};
|
||||
|
@ -100,7 +100,8 @@ impl EGLContext {
|
|||
ptr::null(),
|
||||
context_attributes.as_ptr(),
|
||||
)
|
||||
}).map_err(Error::CreationFailed)?;
|
||||
})
|
||||
.map_err(Error::CreationFailed)?;
|
||||
|
||||
info!(log, "EGL context created");
|
||||
|
||||
|
@ -119,16 +120,15 @@ impl EGLContext {
|
|||
///
|
||||
/// This function is marked unsafe, because the context cannot be made current
|
||||
/// on multiple threads.
|
||||
pub unsafe fn make_current_with_surface<N>(
|
||||
&self,
|
||||
surface: &EGLSurface<N>,
|
||||
) -> Result<(), MakeCurrentError>
|
||||
pub unsafe fn make_current_with_surface<N>(&self, surface: &EGLSurface<N>) -> Result<(), MakeCurrentError>
|
||||
where
|
||||
N: NativeSurface,
|
||||
{
|
||||
let surface_ptr = surface.surface.get();
|
||||
|
||||
wrap_egl_call(|| ffi::egl::MakeCurrent(**self.display, surface_ptr, surface_ptr, self.context)).map(|_| ()).map_err(Into::into)
|
||||
wrap_egl_call(|| ffi::egl::MakeCurrent(**self.display, surface_ptr, surface_ptr, self.context))
|
||||
.map(|_| ())
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Makes the OpenGL context the current context in the current thread with no surface bound.
|
||||
|
@ -138,7 +138,16 @@ impl EGLContext {
|
|||
/// This function is marked unsafe, because the context cannot be made current
|
||||
/// on multiple threads without being unbound again (see `unbind`)
|
||||
pub unsafe fn make_current(&self) -> Result<(), MakeCurrentError> {
|
||||
wrap_egl_call(|| ffi::egl::MakeCurrent(**self.display, ffi::egl::NO_SURFACE, ffi::egl::NO_SURFACE, self.context)).map(|_| ()).map_err(Into::into)
|
||||
wrap_egl_call(|| {
|
||||
ffi::egl::MakeCurrent(
|
||||
**self.display,
|
||||
ffi::egl::NO_SURFACE,
|
||||
ffi::egl::NO_SURFACE,
|
||||
self.context,
|
||||
)
|
||||
})
|
||||
.map(|_| ())
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Returns true if the OpenGL context is the current one in the thread.
|
||||
|
@ -161,7 +170,14 @@ impl EGLContext {
|
|||
/// This does nothing if this context is not the current context
|
||||
pub fn unbind(&self) -> Result<(), MakeCurrentError> {
|
||||
if self.is_current() {
|
||||
wrap_egl_call(|| unsafe { ffi::egl::MakeCurrent(**self.display, ffi::egl::NO_SURFACE, ffi::egl::NO_SURFACE, ffi::egl::NO_CONTEXT)})?;
|
||||
wrap_egl_call(|| unsafe {
|
||||
ffi::egl::MakeCurrent(
|
||||
**self.display,
|
||||
ffi::egl::NO_SURFACE,
|
||||
ffi::egl::NO_SURFACE,
|
||||
ffi::egl::NO_CONTEXT,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
#[cfg(feature = "use_system_lib")]
|
||||
use crate::backend::egl::EGLGraphicsBackend;
|
||||
use crate::backend::egl::{
|
||||
ffi, get_proc_address, native, BufferAccessError, SurfaceCreationError, EGLContext, EGLImages, EGLSurface, Error, Format, EGLError, wrap_egl_call,
|
||||
ffi, get_proc_address, native, wrap_egl_call, BufferAccessError, EGLContext, EGLError, EGLImages,
|
||||
EGLSurface, Error, Format, SurfaceCreationError,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -94,7 +95,9 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
|
|||
|
||||
// the first step is to query the list of extensions without any display, if supported
|
||||
let dp_extensions = unsafe {
|
||||
let p = wrap_egl_call(|| ffi::egl::QueryString(ffi::egl::NO_DISPLAY, ffi::egl::EXTENSIONS as i32)).map_err(Error::InitFailed)?;
|
||||
let p =
|
||||
wrap_egl_call(|| ffi::egl::QueryString(ffi::egl::NO_DISPLAY, ffi::egl::EXTENSIONS as i32))
|
||||
.map_err(Error::InitFailed)?;
|
||||
|
||||
// this possibility is available only with EGL 1.5 or EGL_EXT_platform_base, otherwise
|
||||
// `eglQueryString` returns an error
|
||||
|
@ -108,13 +111,19 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
|
|||
};
|
||||
debug!(log, "EGL No-Display Extensions: {:?}", dp_extensions);
|
||||
|
||||
let display = unsafe { B::get_display(ptr, |e: &str| dp_extensions.iter().any(|s| s == e), log.clone()).map_err(Error::DisplayNotSupported)? };
|
||||
let display = unsafe {
|
||||
B::get_display(ptr, |e: &str| dp_extensions.iter().any(|s| s == e), log.clone())
|
||||
.map_err(Error::DisplayNotSupported)?
|
||||
};
|
||||
|
||||
let egl_version = {
|
||||
let mut major: MaybeUninit<ffi::egl::types::EGLint> = MaybeUninit::uninit();
|
||||
let mut minor: MaybeUninit<ffi::egl::types::EGLint> = MaybeUninit::uninit();
|
||||
|
||||
wrap_egl_call(|| unsafe { ffi::egl::Initialize(display, major.as_mut_ptr(), minor.as_mut_ptr()) }).map_err(Error::InitFailed)?;
|
||||
wrap_egl_call(|| unsafe {
|
||||
ffi::egl::Initialize(display, major.as_mut_ptr(), minor.as_mut_ptr())
|
||||
})
|
||||
.map_err(Error::InitFailed)?;
|
||||
|
||||
let major = unsafe { major.assume_init() };
|
||||
let minor = unsafe { minor.assume_init() };
|
||||
|
@ -128,7 +137,12 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
|
|||
// the list of extensions supported by the client once initialized is different from the
|
||||
// list of extensions obtained earlier
|
||||
let extensions = if egl_version >= (1, 2) {
|
||||
let p = unsafe { CStr::from_ptr(wrap_egl_call(|| ffi::egl::QueryString(display, ffi::egl::EXTENSIONS as i32)).map_err(Error::InitFailed)?) };
|
||||
let p = unsafe {
|
||||
CStr::from_ptr(
|
||||
wrap_egl_call(|| ffi::egl::QueryString(display, ffi::egl::EXTENSIONS as i32))
|
||||
.map_err(Error::InitFailed)?,
|
||||
)
|
||||
};
|
||||
let list = String::from_utf8(p.to_bytes().to_vec()).unwrap_or_else(|_| String::new());
|
||||
list.split(' ').map(|e| e.to_string()).collect::<Vec<_>>()
|
||||
} else {
|
||||
|
@ -139,7 +153,8 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
|
|||
if egl_version >= (1, 2) {
|
||||
return Err(Error::OpenGlesNotSupported(None));
|
||||
}
|
||||
wrap_egl_call(|| unsafe { ffi::egl::BindAPI(ffi::egl::OPENGL_ES_API) }).map_err(|source| Error::OpenGlesNotSupported(Some(source)))?;
|
||||
wrap_egl_call(|| unsafe { ffi::egl::BindAPI(ffi::egl::OPENGL_ES_API) })
|
||||
.map_err(|source| Error::OpenGlesNotSupported(Some(source)))?;
|
||||
|
||||
Ok(EGLDisplay {
|
||||
native: RefCell::new(native),
|
||||
|
@ -212,7 +227,8 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
|
|||
}
|
||||
};
|
||||
|
||||
reqs.create_attributes(&mut out, &self.logger).map_err(|()| Error::NoAvailablePixelFormat)?;
|
||||
reqs.create_attributes(&mut out, &self.logger)
|
||||
.map_err(|()| Error::NoAvailablePixelFormat)?;
|
||||
|
||||
out.push(ffi::egl::NONE as c_int);
|
||||
out
|
||||
|
@ -228,7 +244,8 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
|
|||
0,
|
||||
&mut num_configs,
|
||||
)
|
||||
}).map_err(Error::ConfigFailed)?;
|
||||
})
|
||||
.map_err(Error::ConfigFailed)?;
|
||||
if num_configs == 0 {
|
||||
return Err(Error::NoAvailablePixelFormat);
|
||||
}
|
||||
|
@ -242,8 +259,11 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
|
|||
num_configs,
|
||||
&mut num_configs,
|
||||
)
|
||||
}).map_err(Error::ConfigFailed)?;
|
||||
unsafe { config_ids.set_len(num_configs as usize); }
|
||||
})
|
||||
.map_err(Error::ConfigFailed)?;
|
||||
unsafe {
|
||||
config_ids.set_len(num_configs as usize);
|
||||
}
|
||||
|
||||
// TODO: Deeper swap intervals might have some uses
|
||||
let desired_swap_interval = if attributes.vsync { 1 } else { 0 };
|
||||
|
@ -252,24 +272,28 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
|
|||
.into_iter()
|
||||
.map(|config| unsafe {
|
||||
let mut min_swap_interval = 0;
|
||||
wrap_egl_call(|| ffi::egl::GetConfigAttrib(
|
||||
**self.display,
|
||||
config,
|
||||
ffi::egl::MIN_SWAP_INTERVAL as ffi::egl::types::EGLint,
|
||||
&mut min_swap_interval,
|
||||
))?;
|
||||
wrap_egl_call(|| {
|
||||
ffi::egl::GetConfigAttrib(
|
||||
**self.display,
|
||||
config,
|
||||
ffi::egl::MIN_SWAP_INTERVAL as ffi::egl::types::EGLint,
|
||||
&mut min_swap_interval,
|
||||
)
|
||||
})?;
|
||||
|
||||
if desired_swap_interval < min_swap_interval {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut max_swap_interval = 0;
|
||||
wrap_egl_call(|| ffi::egl::GetConfigAttrib(
|
||||
**self.display,
|
||||
config,
|
||||
ffi::egl::MAX_SWAP_INTERVAL as ffi::egl::types::EGLint,
|
||||
&mut max_swap_interval,
|
||||
))?;
|
||||
wrap_egl_call(|| {
|
||||
ffi::egl::GetConfigAttrib(
|
||||
**self.display,
|
||||
config,
|
||||
ffi::egl::MAX_SWAP_INTERVAL as ffi::egl::types::EGLint,
|
||||
&mut max_swap_interval,
|
||||
)
|
||||
})?;
|
||||
|
||||
if desired_swap_interval > max_swap_interval {
|
||||
return Ok(None);
|
||||
|
@ -277,8 +301,11 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
|
|||
|
||||
Ok(Some(config))
|
||||
})
|
||||
.collect::<Result<Vec<Option<ffi::egl::types::EGLConfig>>, EGLError>>().map_err(Error::ConfigFailed)?
|
||||
.into_iter().flat_map(|x| x).collect::<Vec<_>>();
|
||||
.collect::<Result<Vec<Option<ffi::egl::types::EGLConfig>>, EGLError>>()
|
||||
.map_err(Error::ConfigFailed)?
|
||||
.into_iter()
|
||||
.flat_map(|x| x)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if config_ids.is_empty() {
|
||||
return Err(Error::NoAvailablePixelFormat);
|
||||
|
@ -291,12 +318,15 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
|
|||
macro_rules! attrib {
|
||||
($display:expr, $config:expr, $attr:expr) => {{
|
||||
let mut value = MaybeUninit::uninit();
|
||||
wrap_egl_call(|| ffi::egl::GetConfigAttrib(
|
||||
**$display,
|
||||
$config,
|
||||
$attr as ffi::egl::types::EGLint,
|
||||
value.as_mut_ptr(),
|
||||
)).map_err(Error::ConfigFailed)?;
|
||||
wrap_egl_call(|| {
|
||||
ffi::egl::GetConfigAttrib(
|
||||
**$display,
|
||||
$config,
|
||||
$attr as ffi::egl::types::EGLint,
|
||||
value.as_mut_ptr(),
|
||||
)
|
||||
})
|
||||
.map_err(Error::ConfigFailed)?;
|
||||
value.assume_init()
|
||||
}};
|
||||
};
|
||||
|
@ -343,7 +373,11 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
|
|||
args: N::Arguments,
|
||||
) -> Result<EGLSurface<B::Surface>, SurfaceCreationError<N::Error>> {
|
||||
trace!(self.logger, "Creating EGL window surface.");
|
||||
let surface = self.native.borrow_mut().create_surface(args).map_err(SurfaceCreationError::NativeSurfaceCreationFailed)?;
|
||||
let surface = self
|
||||
.native
|
||||
.borrow_mut()
|
||||
.create_surface(args)
|
||||
.map_err(SurfaceCreationError::NativeSurfaceCreationFailed)?;
|
||||
|
||||
EGLSurface::new(
|
||||
self.display.clone(),
|
||||
|
@ -356,7 +390,8 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLDisplay<B, N> {
|
|||
.map(|x| {
|
||||
debug!(self.logger, "EGL surface successfully created");
|
||||
x
|
||||
}).map_err(SurfaceCreationError::EGLSurfaceCreationFailed)
|
||||
})
|
||||
.map_err(SurfaceCreationError::EGLSurfaceCreationFailed)
|
||||
}
|
||||
|
||||
/// Returns the runtime egl version of this display
|
||||
|
@ -407,7 +442,10 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLGraphicsBackend for EGL
|
|||
if !self.extensions.iter().any(|s| s == "EGL_WL_bind_wayland_display") {
|
||||
return Err(Error::EglExtensionNotSupported(&["EGL_WL_bind_wayland_display"]));
|
||||
}
|
||||
wrap_egl_call(|| unsafe { ffi::egl::BindWaylandDisplayWL(**self.display, display.c_ptr() as *mut _) }).map_err(Error::OtherEGLDisplayAlreadyBound)?;
|
||||
wrap_egl_call(|| unsafe {
|
||||
ffi::egl::BindWaylandDisplayWL(**self.display, display.c_ptr() as *mut _)
|
||||
})
|
||||
.map_err(Error::OtherEGLDisplayAlreadyBound)?;
|
||||
Ok(EGLBufferReader::new(self.display.clone(), display.c_ptr()))
|
||||
}
|
||||
}
|
||||
|
@ -454,7 +492,8 @@ impl EGLBufferReader {
|
|||
ffi::egl::EGL_TEXTURE_FORMAT,
|
||||
&mut format,
|
||||
)
|
||||
}).map_err(|source| BufferAccessError::NotManaged(buffer.clone(), source))?;
|
||||
})
|
||||
.map_err(|source| BufferAccessError::NotManaged(buffer.clone(), source))?;
|
||||
|
||||
let format = match format {
|
||||
x if x == ffi::egl::TEXTURE_RGB as i32 => Format::RGB,
|
||||
|
@ -474,7 +513,8 @@ impl EGLBufferReader {
|
|||
ffi::egl::WIDTH as i32,
|
||||
&mut width,
|
||||
)
|
||||
}).map_err(|source| BufferAccessError::NotManaged(buffer.clone(), source))?;
|
||||
})
|
||||
.map_err(|source| BufferAccessError::NotManaged(buffer.clone(), source))?;
|
||||
|
||||
let mut height: i32 = 0;
|
||||
wrap_egl_call(|| unsafe {
|
||||
|
@ -484,7 +524,8 @@ impl EGLBufferReader {
|
|||
ffi::egl::HEIGHT as i32,
|
||||
&mut height,
|
||||
)
|
||||
}).map_err(|source| BufferAccessError::NotManaged(buffer.clone(), source))?;
|
||||
})
|
||||
.map_err(|source| BufferAccessError::NotManaged(buffer.clone(), source))?;
|
||||
|
||||
let mut inverted: i32 = 0;
|
||||
wrap_egl_call(|| unsafe {
|
||||
|
@ -494,7 +535,8 @@ impl EGLBufferReader {
|
|||
ffi::egl::WAYLAND_Y_INVERTED_WL,
|
||||
&mut inverted,
|
||||
)
|
||||
}).map_err(|source| BufferAccessError::NotManaged(buffer.clone(), source))?;
|
||||
})
|
||||
.map_err(|source| BufferAccessError::NotManaged(buffer.clone(), source))?;
|
||||
|
||||
let mut images = Vec::with_capacity(format.num_planes());
|
||||
for i in 0..format.num_planes() {
|
||||
|
@ -512,7 +554,8 @@ impl EGLBufferReader {
|
|||
buffer.as_ref().c_ptr() as *mut _,
|
||||
out.as_ptr(),
|
||||
)
|
||||
}).map_err(BufferAccessError::EGLImageCreationFailed)?;
|
||||
})
|
||||
.map_err(BufferAccessError::EGLImageCreationFailed)?;
|
||||
image
|
||||
});
|
||||
}
|
||||
|
|
|
@ -48,7 +48,9 @@ pub enum Error {
|
|||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum EGLError {
|
||||
/// EGL is not initialized, or could not be initialized, for the specified EGL display connection.
|
||||
#[error("EGL is not initialized, or could not be initialized, for the specified EGL display connection.")]
|
||||
#[error(
|
||||
"EGL is not initialized, or could not be initialized, for the specified EGL display connection."
|
||||
)]
|
||||
NotInitialized,
|
||||
/// EGL cannot access a requested resource (for example a context is bound in another thread).
|
||||
#[error("EGL cannot access a requested resource (for example a context is bound in another thread).")]
|
||||
|
|
|
@ -19,7 +19,10 @@
|
|||
//! of an EGL-based [`WlBuffer`](wayland_server::protocol::wl_buffer::WlBuffer) for rendering.
|
||||
|
||||
#[cfg(feature = "renderer_gl")]
|
||||
use crate::backend::graphics::{SwapBuffersError as GraphicsSwapBuffersError, gl::{ffi as gl_ffi, GLGraphicsBackend}};
|
||||
use crate::backend::graphics::{
|
||||
gl::{ffi as gl_ffi, GLGraphicsBackend},
|
||||
SwapBuffersError as GraphicsSwapBuffersError,
|
||||
};
|
||||
use nix::libc::c_uint;
|
||||
use std::fmt;
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
|
@ -116,7 +119,7 @@ pub enum SurfaceCreationError<E: std::error::Error + 'static> {
|
|||
NativeSurfaceCreationFailed(#[source] E),
|
||||
/// EGL surface creation failed
|
||||
#[error("EGL surface creation failed. Err: {0:}")]
|
||||
EGLSurfaceCreationFailed(#[source] EGLError)
|
||||
EGLSurfaceCreationFailed(#[source] EGLError),
|
||||
}
|
||||
|
||||
/// Error that can happen when swapping buffers.
|
||||
|
@ -134,14 +137,18 @@ pub enum SwapBuffersError<E: std::error::Error + 'static> {
|
|||
}
|
||||
|
||||
impl<E: std::error::Error> std::convert::TryFrom<SwapBuffersError<E>> for GraphicsSwapBuffersError {
|
||||
type Error=E;
|
||||
type Error = E;
|
||||
fn try_from(value: SwapBuffersError<E>) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
// bad surface is answered with a surface recreation in `swap_buffers`
|
||||
x @ SwapBuffersError::EGLSwapBuffers(EGLError::BadSurface) => Ok(GraphicsSwapBuffersError::TemporaryFailure(Box::new(x))),
|
||||
x @ SwapBuffersError::EGLSwapBuffers(EGLError::BadSurface) => {
|
||||
Ok(GraphicsSwapBuffersError::TemporaryFailure(Box::new(x)))
|
||||
}
|
||||
// the rest is either never happening or are unrecoverable
|
||||
x @ SwapBuffersError::EGLSwapBuffers(_) => Ok(GraphicsSwapBuffersError::ContextLost(Box::new(x))),
|
||||
x @ SwapBuffersError::EGLCreateWindowSurface(_) => Ok(GraphicsSwapBuffersError::ContextLost(Box::new(x))),
|
||||
x @ SwapBuffersError::EGLCreateWindowSurface(_) => {
|
||||
Ok(GraphicsSwapBuffersError::ContextLost(Box::new(x)))
|
||||
}
|
||||
SwapBuffersError::Underlying(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
@ -164,16 +171,22 @@ impl From<MakeCurrentError> for GraphicsSwapBuffersError {
|
|||
|
||||
Except for the first case all of these recoverable. This conversation is mostly used in winit & EglSurface, where compatible context and surfaces are build.
|
||||
*/
|
||||
x @ MakeCurrentError(EGLError::BadAccess) => GraphicsSwapBuffersError::TemporaryFailure(Box::new(x)),
|
||||
x @ MakeCurrentError(EGLError::BadAccess) => {
|
||||
GraphicsSwapBuffersError::TemporaryFailure(Box::new(x))
|
||||
}
|
||||
// BadSurface would result in a recreation in `eglSwapBuffers` -> recoverable
|
||||
x @ MakeCurrentError(EGLError::BadSurface) => GraphicsSwapBuffersError::TemporaryFailure(Box::new(x)),
|
||||
x @ MakeCurrentError(EGLError::BadSurface) => {
|
||||
GraphicsSwapBuffersError::TemporaryFailure(Box::new(x))
|
||||
}
|
||||
/*
|
||||
From khronos docs:
|
||||
If the previous context of the calling thread has unflushed commands, and the previous surface is no longer valid, an EGL_BAD_CURRENT_SURFACE error is generated.
|
||||
|
||||
This does not consern this or future `makeCurrent`-calls.
|
||||
*/
|
||||
x @ MakeCurrentError(EGLError::BadCurrentSurface) => GraphicsSwapBuffersError::TemporaryFailure(Box::new(x)),
|
||||
x @ MakeCurrentError(EGLError::BadCurrentSurface) => {
|
||||
GraphicsSwapBuffersError::TemporaryFailure(Box::new(x))
|
||||
}
|
||||
// the rest is either never happening or are unrecoverable
|
||||
x => GraphicsSwapBuffersError::ContextLost(Box::new(x)),
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Type safe native types for safe context/surface creation
|
||||
|
||||
use super::{ffi, Error, EGLError, wrap_egl_call};
|
||||
use super::{ffi, wrap_egl_call, EGLError, Error};
|
||||
|
||||
#[cfg(feature = "backend_winit")]
|
||||
use std::ptr;
|
||||
|
@ -47,11 +47,19 @@ impl Backend for Wayland {
|
|||
{
|
||||
if has_dp_extension("EGL_KHR_platform_wayland") && ffi::egl::GetPlatformDisplay::is_loaded() {
|
||||
trace!(log, "EGL Display Initialization via EGL_KHR_platform_wayland");
|
||||
wrap_egl_call(|| ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_WAYLAND_KHR, display as *mut _, ptr::null()))
|
||||
wrap_egl_call(|| {
|
||||
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_WAYLAND_KHR, display as *mut _, ptr::null())
|
||||
})
|
||||
} else if has_dp_extension("EGL_EXT_platform_wayland") && ffi::egl::GetPlatformDisplayEXT::is_loaded()
|
||||
{
|
||||
trace!(log, "EGL Display Initialization via EGL_EXT_platform_wayland");
|
||||
wrap_egl_call(|| ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_WAYLAND_EXT, display as *mut _, ptr::null()))
|
||||
wrap_egl_call(|| {
|
||||
ffi::egl::GetPlatformDisplayEXT(
|
||||
ffi::egl::PLATFORM_WAYLAND_EXT,
|
||||
display as *mut _,
|
||||
ptr::null(),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
trace!(log, "Default EGL Display Initialization via GetDisplay");
|
||||
wrap_egl_call(|| ffi::egl::GetDisplay(display as *mut _))
|
||||
|
@ -79,10 +87,14 @@ impl Backend for X11 {
|
|||
{
|
||||
if has_dp_extension("EGL_KHR_platform_x11") && ffi::egl::GetPlatformDisplay::is_loaded() {
|
||||
trace!(log, "EGL Display Initialization via EGL_KHR_platform_x11");
|
||||
wrap_egl_call(|| ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null()))
|
||||
wrap_egl_call(|| {
|
||||
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null())
|
||||
})
|
||||
} else if has_dp_extension("EGL_EXT_platform_x11") && ffi::egl::GetPlatformDisplayEXT::is_loaded() {
|
||||
trace!(log, "EGL Display Initialization via EGL_EXT_platform_x11");
|
||||
wrap_egl_call(|| ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null()))
|
||||
wrap_egl_call(|| {
|
||||
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null())
|
||||
})
|
||||
} else {
|
||||
trace!(log, "Default EGL Display Initialization via GetDisplay");
|
||||
wrap_egl_call(|| ffi::egl::GetDisplay(display as *mut _))
|
||||
|
@ -203,7 +215,9 @@ pub unsafe trait NativeSurface {
|
|||
#[derive(Debug)]
|
||||
pub enum Never {}
|
||||
impl std::fmt::Display for Never {
|
||||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { unreachable!() }
|
||||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
impl std::error::Error for Never {}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! EGL surface related structs
|
||||
|
||||
use super::{ffi, native, EGLError, SwapBuffersError, wrap_egl_call};
|
||||
use super::{ffi, native, wrap_egl_call, EGLError, SwapBuffersError};
|
||||
use crate::backend::egl::display::EGLDisplayHandle;
|
||||
use crate::backend::graphics::PixelFormat;
|
||||
use nix::libc::c_int;
|
||||
|
@ -90,10 +90,16 @@ impl<N: native::NativeSurface> EGLSurface<N> {
|
|||
wrap_egl_call(|| unsafe { ffi::egl::SwapBuffers(**self.display, surface as *const _) })
|
||||
.map_err(SwapBuffersError::EGLSwapBuffers)
|
||||
.and_then(|_| self.native.swap_buffers().map_err(SwapBuffersError::Underlying))
|
||||
} else { Ok(()) };
|
||||
} else {
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// workaround for missing `PartialEq` impl
|
||||
let is_bad_surface = if let Err(SwapBuffersError::EGLSwapBuffers(EGLError::BadSurface)) = result { true } else { false };
|
||||
let is_bad_surface = if let Err(SwapBuffersError::EGLSwapBuffers(EGLError::BadSurface)) = result {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if self.native.needs_recreation() || surface.is_null() || is_bad_surface {
|
||||
self.native.recreate().map_err(SwapBuffersError::Underlying)?;
|
||||
|
@ -101,12 +107,15 @@ impl<N: native::NativeSurface> EGLSurface<N> {
|
|||
let _ = unsafe { ffi::egl::DestroySurface(**self.display, surface as *const _) };
|
||||
}
|
||||
self.surface.set(unsafe {
|
||||
wrap_egl_call(|| ffi::egl::CreateWindowSurface(
|
||||
**self.display,
|
||||
self.config_id,
|
||||
self.native.ptr(),
|
||||
self.surface_attributes.as_ptr(),
|
||||
)).map_err(SwapBuffersError::EGLCreateWindowSurface)?
|
||||
wrap_egl_call(|| {
|
||||
ffi::egl::CreateWindowSurface(
|
||||
**self.display,
|
||||
self.config_id,
|
||||
self.native.ptr(),
|
||||
self.surface_attributes.as_ptr(),
|
||||
)
|
||||
})
|
||||
.map_err(SwapBuffersError::EGLCreateWindowSurface)?
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,10 @@ impl<T: GLGraphicsBackend + 'static> GliumGraphicsBackend<T> {
|
|||
/// Note that destroying a [`Frame`] is immediate, even if vsync is enabled.
|
||||
#[inline]
|
||||
pub fn draw(&self) -> Frame {
|
||||
Frame(glium::Frame::new(self.context.clone(), self.backend.get_framebuffer_dimensions()), self.error_channel.clone())
|
||||
Frame(
|
||||
glium::Frame::new(self.context.clone(), self.backend.get_framebuffer_dimensions()),
|
||||
self.error_channel.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Borrow the underlying backend.
|
||||
|
@ -89,7 +92,7 @@ unsafe impl<T: GLGraphicsBackend> Backend for InternalBackend<T> {
|
|||
SwapBuffersError::ContextLost(err) => {
|
||||
self.1.set(Some(err));
|
||||
GliumSwapBuffersError::ContextLost
|
||||
},
|
||||
}
|
||||
SwapBuffersError::TemporaryFailure(err) => {
|
||||
self.1.set(Some(err));
|
||||
GliumSwapBuffersError::AlreadySwapped
|
||||
|
@ -97,7 +100,9 @@ unsafe impl<T: GLGraphicsBackend> Backend for InternalBackend<T> {
|
|||
// I do not think, this may happen, but why not
|
||||
SwapBuffersError::AlreadySwapped => GliumSwapBuffersError::AlreadySwapped,
|
||||
})
|
||||
} else { Ok(()) }
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
|
||||
|
@ -143,7 +148,9 @@ impl Frame {
|
|||
let err = self.1.take();
|
||||
match (res, err) {
|
||||
(Ok(()), _) => Ok(()),
|
||||
(Err(GliumSwapBuffersError::AlreadySwapped), Some(err)) => Err(SwapBuffersError::TemporaryFailure(err)),
|
||||
(Err(GliumSwapBuffersError::AlreadySwapped), Some(err)) => {
|
||||
Err(SwapBuffersError::TemporaryFailure(err))
|
||||
}
|
||||
(Err(GliumSwapBuffersError::AlreadySwapped), None) => Err(SwapBuffersError::AlreadySwapped),
|
||||
(Err(GliumSwapBuffersError::ContextLost), Some(err)) => Err(SwapBuffersError::ContextLost(err)),
|
||||
_ => unreachable!(),
|
||||
|
@ -152,9 +159,14 @@ impl Frame {
|
|||
}
|
||||
|
||||
impl glium::Surface for Frame {
|
||||
fn clear(&mut self, rect: Option<&glium::Rect>, color: Option<(f32, f32, f32, f32)>, color_srgb: bool,
|
||||
depth: Option<f32>, stencil: Option<i32>)
|
||||
{
|
||||
fn clear(
|
||||
&mut self,
|
||||
rect: Option<&glium::Rect>,
|
||||
color: Option<(f32, f32, f32, f32)>,
|
||||
color_srgb: bool,
|
||||
depth: Option<f32>,
|
||||
stencil: Option<i32>,
|
||||
) {
|
||||
self.0.clear(rect, color, color_srgb, depth, stencil)
|
||||
}
|
||||
|
||||
|
@ -170,36 +182,61 @@ impl glium::Surface for Frame {
|
|||
self.0.get_stencil_buffer_bits()
|
||||
}
|
||||
|
||||
fn draw<'a, 'b, V, I, U>(&mut self, v: V, i: I, program: &glium::Program, uniforms: &U,
|
||||
draw_parameters: &glium::draw_parameters::DrawParameters<'_>) -> Result<(), glium::DrawError> where
|
||||
V: glium::vertex::MultiVerticesSource<'b>, I: Into<glium::index::IndicesSource<'a>>,
|
||||
U: glium::uniforms::Uniforms
|
||||
fn draw<'a, 'b, V, I, U>(
|
||||
&mut self,
|
||||
v: V,
|
||||
i: I,
|
||||
program: &glium::Program,
|
||||
uniforms: &U,
|
||||
draw_parameters: &glium::draw_parameters::DrawParameters<'_>,
|
||||
) -> Result<(), glium::DrawError>
|
||||
where
|
||||
V: glium::vertex::MultiVerticesSource<'b>,
|
||||
I: Into<glium::index::IndicesSource<'a>>,
|
||||
U: glium::uniforms::Uniforms,
|
||||
{
|
||||
self.0.draw(v, i, program, uniforms, draw_parameters)
|
||||
}
|
||||
|
||||
fn blit_from_frame(&self, source_rect: &glium::Rect, target_rect: &glium::BlitTarget,
|
||||
filter: glium::uniforms::MagnifySamplerFilter)
|
||||
{
|
||||
fn blit_from_frame(
|
||||
&self,
|
||||
source_rect: &glium::Rect,
|
||||
target_rect: &glium::BlitTarget,
|
||||
filter: glium::uniforms::MagnifySamplerFilter,
|
||||
) {
|
||||
self.0.blit_from_frame(source_rect, target_rect, filter);
|
||||
}
|
||||
|
||||
fn blit_from_simple_framebuffer(&self, source: &glium::framebuffer::SimpleFrameBuffer<'_>,
|
||||
source_rect: &glium::Rect, target_rect: &glium::BlitTarget,
|
||||
filter: glium::uniforms::MagnifySamplerFilter)
|
||||
{
|
||||
self.0.blit_from_simple_framebuffer(source, source_rect, target_rect, filter)
|
||||
fn blit_from_simple_framebuffer(
|
||||
&self,
|
||||
source: &glium::framebuffer::SimpleFrameBuffer<'_>,
|
||||
source_rect: &glium::Rect,
|
||||
target_rect: &glium::BlitTarget,
|
||||
filter: glium::uniforms::MagnifySamplerFilter,
|
||||
) {
|
||||
self.0
|
||||
.blit_from_simple_framebuffer(source, source_rect, target_rect, filter)
|
||||
}
|
||||
|
||||
fn blit_from_multioutput_framebuffer(&self, source: &glium::framebuffer::MultiOutputFrameBuffer<'_>,
|
||||
source_rect: &glium::Rect, target_rect: &glium::BlitTarget,
|
||||
filter: glium::uniforms::MagnifySamplerFilter)
|
||||
{
|
||||
self.0.blit_from_multioutput_framebuffer(source, source_rect, target_rect, filter)
|
||||
fn blit_from_multioutput_framebuffer(
|
||||
&self,
|
||||
source: &glium::framebuffer::MultiOutputFrameBuffer<'_>,
|
||||
source_rect: &glium::Rect,
|
||||
target_rect: &glium::BlitTarget,
|
||||
filter: glium::uniforms::MagnifySamplerFilter,
|
||||
) {
|
||||
self.0
|
||||
.blit_from_multioutput_framebuffer(source, source_rect, target_rect, filter)
|
||||
}
|
||||
|
||||
fn blit_color<S>(&self, source_rect: &glium::Rect, target: &S, target_rect: &glium::BlitTarget,
|
||||
filter: glium::uniforms::MagnifySamplerFilter) where S: glium::Surface
|
||||
fn blit_color<S>(
|
||||
&self,
|
||||
source_rect: &glium::Rect,
|
||||
target: &S,
|
||||
target_rect: &glium::BlitTarget,
|
||||
filter: glium::uniforms::MagnifySamplerFilter,
|
||||
) where
|
||||
S: glium::Surface,
|
||||
{
|
||||
self.0.blit_color(source_rect, target, target_rect, filter)
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ pub enum Error {
|
|||
EGL(#[from] EGLError),
|
||||
/// Surface Creation failed
|
||||
#[error("Surface creation failed: {0}")]
|
||||
SurfaceCreationError(#[from] SurfaceCreationError<EGLError>)
|
||||
SurfaceCreationError(#[from] SurfaceCreationError<EGLError>),
|
||||
}
|
||||
|
||||
enum Window {
|
||||
|
@ -281,7 +281,9 @@ impl GLGraphicsBackend for WinitGraphicsBackend {
|
|||
fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> {
|
||||
trace!(self.logger, "Swapping buffers");
|
||||
match *self.window {
|
||||
Window::Wayland { ref surface, .. } => surface.swap_buffers().map_err(|err| err.try_into().unwrap()),
|
||||
Window::Wayland { ref surface, .. } => {
|
||||
surface.swap_buffers().map_err(|err| err.try_into().unwrap())
|
||||
}
|
||||
Window::X11 { ref surface, .. } => surface.swap_buffers().map_err(|err| err.try_into().unwrap()),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue