cargo fmt

This commit is contained in:
Victor Brekenfeld 2021-05-26 19:12:45 +02:00
parent 890a17189b
commit 12e80ca2c6
17 changed files with 990 additions and 255 deletions

View File

@ -15,7 +15,7 @@ use smithay::{
}, },
utils::Rectangle, utils::Rectangle,
wayland::{ wayland::{
compositor::{roles::Role, SubsurfaceRole, TraversalAction, Damage}, compositor::{roles::Role, Damage, SubsurfaceRole, TraversalAction},
data_device::DnDIconRole, data_device::DnDIconRole,
seat::CursorImageRole, seat::CursorImageRole,
}, },
@ -61,7 +61,15 @@ where
(0, 0) (0, 0)
} }
}; };
draw_surface_tree(renderer, frame, surface, egl_buffer_reader, (x - dx, y - dy), token, log) draw_surface_tree(
renderer,
frame,
surface,
egl_buffer_reader,
(x - dx, y - dy),
token,
log,
)
} }
fn draw_surface_tree<R, E, F, T>( fn draw_surface_tree<R, E, F, T>(
@ -92,7 +100,12 @@ where
if let Some(buffer) = data.current_state.buffer.take() { if let Some(buffer) = data.current_state.buffer.take() {
match renderer.import_buffer(&buffer, &attributes, egl_buffer_reader) { match renderer.import_buffer(&buffer, &attributes, egl_buffer_reader) {
Ok(m) => { Ok(m) => {
let buffer = if smithay::wayland::shm::with_buffer_contents(&buffer, |_,_| ()).is_ok() { let buffer = if smithay::wayland::shm::with_buffer_contents(
&buffer,
|_, _| (),
)
.is_ok()
{
buffer.release(); buffer.release();
None None
} else { } else {
@ -111,7 +124,8 @@ where
} }
} }
// Now, should we be drawn ? // Now, should we be drawn ?
if data.texture.is_some() {// if yes, also process the children if data.texture.is_some() {
// if yes, also process the children
if Role::<SubsurfaceRole>::has(role) { if Role::<SubsurfaceRole>::has(role) {
x += data.current_state.sub_location.0; x += data.current_state.sub_location.0;
y += data.current_state.sub_location.1; y += data.current_state.sub_location.1;

664
anvil/src/raw.rs Normal file
View File

@ -0,0 +1,664 @@
use std::{
cell::RefCell,
collections::hash_map::{Entry, HashMap},
io::Error as IoError,
fs::{File, OpenOptions},
rc::Rc,
os::unix::io::{AsRawFd, RawFd},
sync::{atomic::Ordering, Arc, Mutex},
time::Duration,
};
use image::ImageBuffer;
use slog::Logger;
#[cfg(feature = "egl")]
use smithay::{
backend::egl::display::EGLBufferReader,
};
use smithay::{
backend::{
drm::{device_bind, DeviceHandler, DrmDevice, DrmError, DrmRenderSurface},
egl::{EGLContext, EGLDisplay},
renderer::{
gles2::{Gles2Renderer, Gles2Texture},
Frame, Renderer, Transform,
},
SwapBuffersError,
},
reexports::{
calloop::{
generic::Generic,
timer::{Timer, TimerHandle},
EventLoop, LoopHandle, Source,
},
drm::{
self,
control::{
connector::{Info as ConnectorInfo, State as ConnectorState},
crtc,
encoder::Info as EncoderInfo,
Device as ControlDevice,
},
},
gbm::{BufferObject as GbmBuffer, Device as GbmDevice},
nix::sys::stat::dev_t,
wayland_server::{
protocol::{wl_output, wl_surface, wl_buffer},
Display, Global,
},
},
utils::Rectangle,
wayland::{
compositor::CompositorToken,
output::{Mode, Output, PhysicalProperties},
seat::CursorImageStatus,
},
};
use crate::drawing::*;
use crate::shell::{MyWindowMap, Roles};
use crate::state::AnvilState;
pub struct FileWrapper(File);
impl AsRawFd for FileWrapper {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
impl Clone for FileWrapper {
fn clone(&self) -> Self {
FileWrapper(self.0.try_clone().unwrap())
}
}
pub fn run_raw(
display: Rc<RefCell<Display>>,
event_loop: &mut EventLoop<AnvilState>,
path: impl AsRef<str>,
log: Logger,
) -> Result<(), ()> {
let name = display
.borrow_mut()
.add_socket_auto()
.unwrap()
.into_string()
.unwrap();
info!(log, "Listening on wayland socket"; "name" => name.clone());
::std::env::set_var("WAYLAND_DISPLAY", name);
#[cfg(feature = "egl")]
let egl_buffer_reader = Rc::new(RefCell::new(None));
let output_map = Rc::new(RefCell::new(Vec::new()));
/*
* Initialize the compositor
*/
let mut state = AnvilState::init(
display.clone(),
event_loop.handle(),
#[cfg(feature = "egl")]
egl_buffer_reader.clone(),
None,
None,
log.clone(),
);
/*
* Initialize the backend
*/
// Try to open the device
let mut options = OpenOptions::new();
options.read(true);
options.write(true);
let _backend = if let Some((mut device, gbm)) = options.open(path.as_ref())
.ok()
.and_then(|fd| {
let file = FileWrapper(fd);
match {
(
DrmDevice::new(file.clone(), true, log.clone()),
GbmDevice::new(file),
)
} {
(Ok(drm), Ok(gbm)) => Some((drm, gbm)),
(Err(err), _) => {
error!(
log,
"Aborting initializing {:?}, because of drm error: {}", path.as_ref(), err
);
None
}
(_, Err(err)) => {
// TODO try DumbBuffer allocator in this case
error!(
log,
"Aborting initializing {:?}, because of gbm error: {}", path.as_ref(), err
);
None
}
}
})
{
let egl = match EGLDisplay::new(&gbm, log.clone()) {
Ok(display) => display,
Err(err) => {
warn!(
log,
"Skipping device {:?}, because of egl display error: {}", path.as_ref(), err
);
return Err(());
}
};
let context = match EGLContext::new(&egl, log.clone()) {
Ok(context) => context,
Err(err) => {
warn!(
log,
"Skipping device {:?}, because of egl context error: {}", path.as_ref(), err
);
return Err(());
}
};
#[cfg(feature = "egl")]
{
info!(
log,
"Initializing EGL Hardware Acceleration via {:?}", path.as_ref()
);
*egl_buffer_reader.borrow_mut() = egl.bind_wl_display(&*display.borrow()).ok();
}
let backends = Rc::new(RefCell::new(scan_connectors(
&mut device,
&gbm,
&egl,
&context,
&mut *display.borrow_mut(),
&mut *output_map.borrow_mut(),
&log,
)));
let bytes = include_bytes!("../resources/cursor2.rgba");
let pointer_image = {
let context = EGLContext::new_shared(&egl, &context, log.clone()).unwrap();
let mut renderer = unsafe { Gles2Renderer::new(context, log.clone()).unwrap() };
let image = ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap();
renderer
.import_bitmap(&image)
.expect("Failed to load pointer")
};
// Set the handler.
// Note: if you replicate this (very simple) structure, it is rather easy
// to introduce reference cycles with Rc. Be sure about your drop order
let renderer = Rc::new(DrmRenderer {
#[cfg(feature = "egl")]
egl_buffer_reader:egl_buffer_reader.borrow().clone(),
compositor_token: state.ctoken,
backends: backends.clone(),
window_map: state.window_map.clone(),
output_map: output_map.clone(),
pointer_location: state.pointer_location.clone(),
pointer_image,
cursor_status: state.cursor_status.clone(),
dnd_icon: state.dnd_icon.clone(),
logger: log.clone(),
start_time: std::time::Instant::now(),
});
device.set_handler(DrmHandlerImpl {
renderer,
loop_handle: event_loop.handle(),
});
let event_source = device_bind(&event_loop.handle(), device)
.map_err(|e| -> IoError { e.into() })
.unwrap();
trace!(log, "Backends: {:?}", backends.borrow().keys());
for renderer in backends.borrow_mut().values() {
// render first frame
trace!(log, "Scheduling frame");
schedule_initial_render(renderer.clone(), &event_loop.handle(), log.clone());
}
BackendData {
event_source,
surfaces: backends,
egl,
context,
}
} else {
return Err(());
};
/*
* And run our loop
*/
while state.running.load(Ordering::SeqCst) {
if event_loop
.dispatch(Some(Duration::from_millis(16)), &mut state)
.is_err()
{
state.running.store(false, Ordering::SeqCst);
} else {
display.borrow_mut().flush_clients(&mut state);
state.window_map.borrow_mut().refresh();
}
}
// Cleanup stuff
state.window_map.borrow_mut().clear();
Ok(())
}
pub fn scan_connectors(
device: &mut DrmDevice<FileWrapper>,
gbm: &GbmDevice<FileWrapper>,
egl: &EGLDisplay,
context: &EGLContext,
display: &mut Display,
output_map: &mut Vec<MyOutput>,
logger: &::slog::Logger,
) -> HashMap<crtc::Handle, Rc<RefCell<RenderSurface>>> {
// Get a set of all modesetting resource handles (excluding planes):
let res_handles = device.resource_handles().unwrap();
// Use first connected connector
let connector_infos: Vec<ConnectorInfo> = res_handles
.connectors()
.iter()
.map(|conn| device.get_connector(*conn).unwrap())
.filter(|conn| conn.state() == ConnectorState::Connected)
.inspect(|conn| info!(logger, "Connected: {:?}", conn.interface()))
.collect();
let mut backends = HashMap::new();
// very naive way of finding good crtc/encoder/connector combinations. This problem is np-complete
for connector_info in connector_infos {
let encoder_infos = connector_info
.encoders()
.iter()
.filter_map(|e| *e)
.flat_map(|encoder_handle| device.get_encoder(encoder_handle))
.collect::<Vec<EncoderInfo>>();
'outer: for encoder_info in encoder_infos {
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
if let Entry::Vacant(entry) = backends.entry(crtc) {
info!(
logger,
"Trying to setup connector {:?}-{} with crtc {:?}",
connector_info.interface(),
connector_info.interface_id(),
crtc,
);
let context = match EGLContext::new_shared(egl, context, logger.clone()) {
Ok(context) => context,
Err(err) => {
warn!(logger, "Failed to create EGLContext: {}", err);
continue;
}
};
let renderer = match unsafe { Gles2Renderer::new(context, logger.clone()) } {
Ok(renderer) => renderer,
Err(err) => {
warn!(logger, "Failed to create Gles2 Renderer: {}", err);
continue;
}
};
let surface = match device.create_surface(
crtc,
connector_info.modes()[0],
&[connector_info.handle()],
) {
Ok(surface) => surface,
Err(err) => {
warn!(logger, "Failed to create drm surface: {}", err);
continue;
}
};
let renderer =
match DrmRenderSurface::new(surface, gbm.clone(), renderer, logger.clone()) {
Ok(renderer) => renderer,
Err(err) => {
warn!(logger, "Failed to create rendering surface: {}", err);
continue;
}
};
output_map.push(MyOutput::new(
display,
device.device_id(),
crtc,
connector_info,
logger.clone(),
));
entry.insert(Rc::new(RefCell::new(renderer)));
break 'outer;
}
}
}
}
backends
}
pub struct MyOutput {
pub device_id: dev_t,
pub crtc: crtc::Handle,
pub size: (u32, u32),
_wl: Output,
global: Option<Global<wl_output::WlOutput>>,
}
impl MyOutput {
fn new(
display: &mut Display,
device_id: dev_t,
crtc: crtc::Handle,
conn: ConnectorInfo,
logger: ::slog::Logger,
) -> MyOutput {
let (output, global) = Output::new(
display,
format!("{:?}", conn.interface()),
PhysicalProperties {
width: conn.size().unwrap_or((0, 0)).0 as i32,
height: conn.size().unwrap_or((0, 0)).1 as i32,
subpixel: wl_output::Subpixel::Unknown,
make: "Smithay".into(),
model: "Generic DRM".into(),
},
logger,
);
let mode = conn.modes()[0];
let (w, h) = mode.size();
output.change_current_state(
Some(Mode {
width: w as i32,
height: h as i32,
refresh: (mode.vrefresh() * 1000) as i32,
}),
None,
None,
);
output.set_preferred(Mode {
width: w as i32,
height: h as i32,
refresh: (mode.vrefresh() * 1000) as i32,
});
MyOutput {
device_id,
crtc,
size: (w as u32, h as u32),
_wl: output,
global: Some(global),
}
}
}
impl Drop for MyOutput {
fn drop(&mut self) {
self.global.take().unwrap().destroy();
}
}
pub type RenderSurface = DrmRenderSurface<FileWrapper, GbmDevice<FileWrapper>, Gles2Renderer, GbmBuffer<()>>;
struct BackendData {
surfaces: Rc<RefCell<HashMap<crtc::Handle, Rc<RefCell<RenderSurface>>>>>,
context: EGLContext,
egl: EGLDisplay,
event_source: Source<Generic<DrmDevice<FileWrapper>>>,
}
pub struct DrmHandlerImpl<Data: 'static> {
renderer: Rc<DrmRenderer>,
loop_handle: LoopHandle<Data>,
}
impl<Data: 'static> DeviceHandler for DrmHandlerImpl<Data> {
fn vblank(&mut self, crtc: crtc::Handle) {
self.renderer.clone().render(crtc, None, Some(&self.loop_handle))
}
fn error(&mut self, error: DrmError) {
error!(self.renderer.logger, "{:?}", error);
}
}
pub struct DrmRenderer {
#[cfg(feature = "egl")]
egl_buffer_reader: Option<EGLBufferReader>,
compositor_token: CompositorToken<Roles>,
backends: Rc<RefCell<HashMap<crtc::Handle, Rc<RefCell<RenderSurface>>>>>,
window_map: Rc<RefCell<MyWindowMap>>,
output_map: Rc<RefCell<Vec<MyOutput>>>,
pointer_location: Rc<RefCell<(f64, f64)>>,
pointer_image: Gles2Texture,
cursor_status: Arc<Mutex<CursorImageStatus>>,
dnd_icon: Arc<Mutex<Option<wl_surface::WlSurface>>>,
logger: ::slog::Logger,
start_time: std::time::Instant,
}
impl DrmRenderer {
fn render<Data: 'static>(
self: Rc<Self>,
crtc: crtc::Handle,
timer: Option<TimerHandle<(std::rc::Weak<DrmRenderer>, crtc::Handle)>>,
evt_handle: Option<&LoopHandle<Data>>,
) {
if let Some(surface) = self.backends.borrow().get(&crtc) {
let result = DrmRenderer::render_surface(
&mut *surface.borrow_mut(),
#[cfg(feature = "egl")]
self.egl_buffer_reader.as_ref(),
crtc,
&mut *self.window_map.borrow_mut(),
&mut *self.output_map.borrow_mut(),
&self.compositor_token,
&*self.pointer_location.borrow(),
&self.pointer_image,
&*self.dnd_icon.lock().unwrap(),
&mut *self.cursor_status.lock().unwrap(),
&self.logger,
);
if let Err(err) = result {
warn!(self.logger, "Error during rendering: {:?}", err);
let reschedule = match err {
SwapBuffersError::AlreadySwapped => false,
SwapBuffersError::TemporaryFailure(err) => !matches!(
err.downcast_ref::<DrmError>(),
Some(&DrmError::DeviceInactive)
| Some(&DrmError::Access {
source: drm::SystemError::PermissionDenied,
..
})
),
SwapBuffersError::ContextLost(err) => panic!("Rendering loop lost: {}", err),
};
if reschedule {
debug!(self.logger, "Rescheduling");
match (timer, evt_handle) {
(Some(handle), _) => {
let _ = handle.add_timeout(
Duration::from_millis(1000 /*a seconds*/ / 60 /*refresh rate*/),
(Rc::downgrade(&self), crtc),
);
}
(None, Some(evt_handle)) => {
let timer = Timer::new().unwrap();
let handle = timer.handle();
let _ = handle.add_timeout(
Duration::from_millis(1000 /*a seconds*/ / 60 /*refresh rate*/),
(Rc::downgrade(&self), crtc),
);
evt_handle
.insert_source(timer, |(renderer, crtc), handle, _data| {
if let Some(renderer) = renderer.upgrade() {
renderer.render(
crtc,
Some(handle.clone()),
Option::<&LoopHandle<Data>>::None,
);
}
})
.unwrap();
}
_ => unreachable!(),
}
}
} else {
// TODO: only send drawn windows the frames callback
// Send frame events so that client start drawing their next frame
self.window_map
.borrow()
.send_frames(self.start_time.elapsed().as_millis() as u32);
}
}
}
#[allow(clippy::too_many_arguments)]
fn render_surface(
surface: &mut RenderSurface,
#[cfg(feature = "egl")] egl_buffer_reader: Option<&EGLBufferReader>,
crtc: crtc::Handle,
window_map: &mut MyWindowMap,
output_map: &mut Vec<MyOutput>,
compositor_token: &CompositorToken<Roles>,
pointer_location: &(f64, f64),
pointer_image: &Gles2Texture,
dnd_icon: &Option<wl_surface::WlSurface>,
cursor_status: &mut CursorImageStatus,
logger: &slog::Logger,
) -> Result<(), SwapBuffersError> {
#[cfg(not(feature = "egl"))]
let egl_buffer_reader = None;
surface.frame_submitted()?;
// get output coordinates
let (x, y) = output_map
.iter()
.take_while(|output| output.crtc != crtc)
.fold((0u32, 0u32), |pos, output| (pos.0 + output.size.0, pos.1));
let (width, height) = output_map
.iter()
.find(|output| output.crtc == crtc)
.map(|output| output.size)
.unwrap_or((0, 0)); // in this case the output will be removed.
// and draw in sync with our monitor
surface.render(|renderer, frame| -> Result<(), SwapBuffersError> {
frame.clear([0.8, 0.8, 0.9, 1.0])?;
// draw the surfaces
draw_windows(
renderer,
frame,
egl_buffer_reader,
window_map,
Some(Rectangle {
x: x as i32,
y: y as i32,
width: width as i32,
height: height as i32,
}),
*compositor_token,
logger,
)?;
// get pointer coordinates
let (ptr_x, ptr_y) = *pointer_location;
let ptr_x = ptr_x.trunc().abs() as i32 - x as i32;
let ptr_y = ptr_y.trunc().abs() as i32 - y as i32;
// set cursor
if ptr_x >= 0 && ptr_x < width as i32 && ptr_y >= 0 && ptr_y < height as i32 {
// draw the dnd icon if applicable
{
if let Some(ref wl_surface) = dnd_icon.as_ref() {
if wl_surface.as_ref().is_alive() {
draw_dnd_icon(
renderer,
frame,
wl_surface,
egl_buffer_reader,
(ptr_x, ptr_y),
*compositor_token,
logger,
)?;
}
}
}
// draw the cursor as relevant
{
// reset the cursor if the surface is no longer alive
let mut reset = false;
if let CursorImageStatus::Image(ref surface) = *cursor_status {
reset = !surface.as_ref().is_alive();
}
if reset {
*cursor_status = CursorImageStatus::Default;
}
if let CursorImageStatus::Image(ref wl_surface) = *cursor_status {
draw_cursor(
renderer,
frame,
wl_surface,
egl_buffer_reader,
(ptr_x, ptr_y),
*compositor_token,
logger,
)?;
} else {
frame.render_texture_at(pointer_image, (ptr_x, ptr_y), Transform::Normal, 1.0)?;
}
}
}
Ok(())
}).map_err(Into::<SwapBuffersError>::into).and_then(|x| x)
}
}
fn schedule_initial_render<Data: 'static>(
renderer: Rc<RefCell<RenderSurface>>,
evt_handle: &LoopHandle<Data>,
logger: ::slog::Logger,
) {
let result = {
let mut renderer = renderer.borrow_mut();
// Does not matter if we render an empty frame
renderer
.render(|_, frame| {
frame
.clear([0.8, 0.8, 0.9, 1.0])
.map_err(Into::<SwapBuffersError>::into)
})
.map_err(Into::<SwapBuffersError>::into)
.and_then(|x| x.map_err(Into::<SwapBuffersError>::into))
};
if let Err(err) = result {
match err {
SwapBuffersError::AlreadySwapped => {}
SwapBuffersError::TemporaryFailure(err) => {
// TODO dont reschedule after 3(?) retries
warn!(logger, "Failed to submit page_flip: {}", err);
let handle = evt_handle.clone();
evt_handle.insert_idle(move |_| schedule_initial_render(renderer, &handle, logger));
}
SwapBuffersError::ContextLost(err) => panic!("Rendering loop lost: {}", err),
}
}
}

View File

@ -767,7 +767,8 @@ impl DrmRenderer {
.unwrap_or((0, 0)); // in this case the output will be removed. .unwrap_or((0, 0)); // in this case the output will be removed.
// and draw in sync with our monitor // and draw in sync with our monitor
surface.render(|renderer, frame| { surface
.render(|renderer, frame| {
frame.clear([0.8, 0.8, 0.9, 1.0])?; frame.clear([0.8, 0.8, 0.9, 1.0])?;
// draw the surfaces // draw the surfaces
draw_windows( draw_windows(
@ -836,7 +837,8 @@ impl DrmRenderer {
} }
Ok(()) Ok(())
}).map_err(Into::<SwapBuffersError>::into) })
.map_err(Into::<SwapBuffersError>::into)
.and_then(|x| x) .and_then(|x| x)
.map_err(Into::<SwapBuffersError>::into) .map_err(Into::<SwapBuffersError>::into)
} }

View File

@ -99,8 +99,8 @@ pub fn run_winit(
{ {
let mut renderer = renderer.borrow_mut(); let mut renderer = renderer.borrow_mut();
let result = renderer
let result = renderer.render(|renderer, frame| { .render(|renderer, frame| {
frame.clear([0.8, 0.8, 0.9, 1.0])?; frame.clear([0.8, 0.8, 0.9, 1.0])?;
// draw the windows // draw the windows
@ -162,7 +162,8 @@ pub fn run_winit(
} }
Ok(()) Ok(())
}).map_err(Into::<SwapBuffersError>::into) })
.map_err(Into::<SwapBuffersError>::into)
.and_then(|x| x.into()); .and_then(|x| x.into());
renderer.window().set_cursor_visible(cursor_visible); renderer.window().set_cursor_visible(cursor_visible);

View File

@ -122,7 +122,9 @@ fn main() {
.unwrap(); .unwrap();
// Start rendering // Start rendering
surface.commit([(framebuffer, surface.plane())].iter(), true).unwrap(); surface
.commit([(framebuffer, surface.plane())].iter(), true)
.unwrap();
// Run // Run
event_loop.run(None, &mut (), |_| {}).unwrap(); event_loop.run(None, &mut (), |_| {}).unwrap();
@ -158,7 +160,9 @@ impl DeviceHandler for DrmHandlerImpl {
} }
let fb = self.current.userdata().unwrap(); let fb = self.current.userdata().unwrap();
self.surface.page_flip([(fb, self.surface.plane())].iter(), true).unwrap(); self.surface
.page_flip([(fb, self.surface.plane())].iter(), true)
.unwrap();
} }
fn error(&mut self, error: DrmError) { fn error(&mut self, error: DrmError) {

View File

@ -111,9 +111,14 @@ where
/// The swapchain has an internal maximum of four re-usable buffers. /// The swapchain has an internal maximum of four re-usable buffers.
/// This function returns the first free one. /// This function returns the first free one.
pub fn acquire(&mut self) -> Result<Option<Slot<B, U>>, A::Error> { pub fn acquire(&mut self) -> Result<Option<Slot<B, U>>, A::Error> {
if let Some(free_slot) = self.slots.iter_mut().find(|s| !s.acquired.swap(true, Ordering::SeqCst)) { if let Some(free_slot) = self
.slots
.iter_mut()
.find(|s| !s.acquired.swap(true, Ordering::SeqCst))
{
if free_slot.buffer.is_none() { if free_slot.buffer.is_none() {
let mut free_slot = Arc::get_mut(free_slot).expect("Acquired was false, but Arc is not unique?"); let mut free_slot =
Arc::get_mut(free_slot).expect("Acquired was false, but Arc is not unique?");
free_slot.buffer = Some(self.allocator.create_buffer( free_slot.buffer = Some(self.allocator.create_buffer(
self.width, self.width,
self.height, self.height,

View File

@ -90,7 +90,9 @@ impl<A: AsRawFd + 'static> LegacyDrmDevice<A> {
for crtc in res_handles.crtcs() { for crtc in res_handles.crtcs() {
#[allow(deprecated)] #[allow(deprecated)]
let _ = self.fd.set_cursor(*crtc, Option::<&drm::control::dumbbuffer::DumbBuffer>::None); let _ = self
.fd
.set_cursor(*crtc, Option::<&drm::control::dumbbuffer::DumbBuffer>::None);
// null commit (necessary to trigger removal on the kernel side with the legacy api.) // null commit (necessary to trigger removal on the kernel side with the legacy api.)
self.fd self.fd
.set_crtc(*crtc, None, (0, 0), &[], None) .set_crtc(*crtc, None, (0, 0), &[], None)

View File

@ -5,18 +5,15 @@ use std::rc::Rc;
use std::sync::{atomic::AtomicBool, Arc}; use std::sync::{atomic::AtomicBool, Arc};
use calloop::{generic::Generic, InsertError, LoopHandle, Source}; use calloop::{generic::Generic, InsertError, LoopHandle, Source};
use drm::control::{ use drm::control::{connector, crtc, Device as ControlDevice, Event, Mode, ResourceHandles};
connector, crtc, Device as ControlDevice, Event, Mode,
ResourceHandles,
};
use drm::{ClientCapability, Device as BasicDevice}; use drm::{ClientCapability, Device as BasicDevice};
use nix::libc::dev_t; use nix::libc::dev_t;
use nix::sys::stat::fstat; use nix::sys::stat::fstat;
pub(super) mod atomic; pub(super) mod atomic;
pub(super) mod legacy; pub(super) mod legacy;
use super::{error::Error, Planes, planes};
use super::surface::{atomic::AtomicDrmSurface, legacy::LegacyDrmSurface, DrmSurface, DrmSurfaceInternal}; use super::surface::{atomic::AtomicDrmSurface, legacy::LegacyDrmSurface, DrmSurface, DrmSurfaceInternal};
use super::{error::Error, planes, Planes};
use atomic::AtomicDrmDevice; use atomic::AtomicDrmDevice;
use legacy::LegacyDrmDevice; use legacy::LegacyDrmDevice;
@ -337,8 +334,6 @@ impl<A: AsRawFd + 'static> DrmDevice<A> {
} }
} }
/// Trait to receive events of a bound [`DrmDevice`] /// Trait to receive events of a bound [`DrmDevice`]
/// ///
/// See [`device_bind`] /// See [`device_bind`]

View File

@ -74,7 +74,7 @@ pub use error::Error as DrmError;
pub use render::{DrmRenderSurface, Error as DrmRenderError}; pub use render::{DrmRenderSurface, Error as DrmRenderError};
pub use surface::DrmSurface; pub use surface::DrmSurface;
use drm::control::{plane, crtc, Device as ControlDevice, PlaneType}; use drm::control::{crtc, plane, Device as ControlDevice, PlaneType};
/// A set of planes as supported by a crtc /// A set of planes as supported by a crtc
pub struct Planes { pub struct Planes {
@ -86,7 +86,11 @@ pub struct Planes {
pub overlay: Vec<plane::Handle>, pub overlay: Vec<plane::Handle>,
} }
fn planes(dev: &impl ControlDevice, crtc: &crtc::Handle, has_universal_planes: bool) -> Result<Planes, DrmError> { fn planes(
dev: &impl ControlDevice,
crtc: &crtc::Handle,
has_universal_planes: bool,
) -> Result<Planes, DrmError> {
let mut primary = None; let mut primary = None;
let mut cursor = None; let mut cursor = None;
let mut overlay = Vec::new(); let mut overlay = Vec::new();
@ -127,16 +131,8 @@ fn planes(dev: &impl ControlDevice, crtc: &crtc::Handle, has_universal_planes: b
Ok(Planes { Ok(Planes {
primary: primary.expect("Crtc has no primary plane"), primary: primary.expect("Crtc has no primary plane"),
cursor: if has_universal_planes { cursor: if has_universal_planes { cursor } else { None },
cursor overlay: if has_universal_planes { overlay } else { Vec::new() },
} else {
None
},
overlay: if has_universal_planes {
overlay
} else {
Vec::new()
},
}) })
} }

View File

@ -7,14 +7,12 @@ use drm::control::{connector, crtc, framebuffer, plane, Device, Mode};
use gbm::{BufferObject, BufferObjectFlags, Device as GbmDevice}; use gbm::{BufferObject, BufferObjectFlags, Device as GbmDevice};
use super::{device::DevPath, surface::DrmSurfaceInternal, DrmError, DrmSurface}; use super::{device::DevPath, surface::DrmSurfaceInternal, DrmError, DrmSurface};
use crate::backend::renderer::{Bind, Frame, Renderer, Texture, Transform}; use crate::backend::allocator::{
use crate::backend::SwapBuffersError;
use crate::backend::{
allocator::{
dmabuf::{AsDmabuf, Dmabuf}, dmabuf::{AsDmabuf, Dmabuf},
Allocator, Buffer, Format, Fourcc, Modifier, Slot, Swapchain, Allocator, Buffer, Format, Fourcc, Modifier, Slot, Swapchain,
},
}; };
use crate::backend::renderer::{Bind, Frame, Renderer, Texture, Transform};
use crate::backend::SwapBuffersError;
/// Simplified by limited abstraction to link single [`DrmSurface`]s to renderers. /// Simplified by limited abstraction to link single [`DrmSurface`]s to renderers.
/// ///
@ -161,9 +159,12 @@ where
.map_err(Error::<E1, E2, E3>::RenderError) .map_err(Error::<E1, E2, E3>::RenderError)
.and_then(|_| { .and_then(|_| {
renderer renderer
.render(mode.size().0 as u32, mode.size().1 as u32, Transform::Normal, |_, frame| { .render(
frame.clear([0.0, 0.0, 0.0, 1.0]) mode.size().0 as u32,
}) mode.size().1 as u32,
Transform::Normal,
|_, frame| frame.clear([0.0, 0.0, 0.0, 1.0]),
)
.map_err(Error::RenderError) .map_err(Error::RenderError)
}) })
.and_then(|_| renderer.unbind().map_err(Error::RenderError)) .and_then(|_| renderer.unbind().map_err(Error::RenderError))
@ -217,7 +218,7 @@ where
/// and this surface set a the rendering target. /// and this surface set a the rendering target.
pub fn render<F, S>(&mut self, rendering: F) -> Result<S, Error<E1, E2, E3>> pub fn render<F, S>(&mut self, rendering: F) -> Result<S, Error<E1, E2, E3>>
where where
F: FnOnce(&mut R, &mut <R as Renderer>::Frame) -> S F: FnOnce(&mut R, &mut <R as Renderer>::Frame) -> S,
{ {
let mode = self.drm.pending_mode(); let mode = self.drm.pending_mode();
let (width, height) = (mode.size().0 as u32, mode.size().1 as u32); let (width, height) = (mode.size().0 as u32, mode.size().1 as u32);

View File

@ -380,7 +380,12 @@ impl<A: AsRawFd + 'static> AtomicDrmSurface<A> {
Ok(()) Ok(())
} }
pub fn use_plane(&self, plane: plane::Handle, position: (i32, i32), size: (u32, u32)) -> Result<(), Error> { pub fn use_plane(
&self,
plane: plane::Handle,
position: (i32, i32),
size: (u32, u32),
) -> Result<(), Error> {
let info = PlaneInfo { let info = PlaneInfo {
handle: plane, handle: plane,
x: position.0, x: position.0,
@ -399,20 +404,26 @@ impl<A: AsRawFd + 'static> AtomicDrmSurface<A> {
&mut [].iter(), &mut [].iter(),
self.plane, self.plane,
&new_planes, &new_planes,
Some([(self.create_test_buffer(pending.mode.size())?, self.plane)] Some(
[(self.create_test_buffer(pending.mode.size())?, self.plane)]
.iter() .iter()
.chain(new_planes.iter().map(|info| { .chain(
match self.create_test_buffer((info.w as u16, info.h as u16)) { new_planes
.iter()
.map(
|info| match self.create_test_buffer((info.w as u16, info.h as u16)) {
Ok(test_buff) => Ok((test_buff, info.handle)), Ok(test_buff) => Ok((test_buff, info.handle)),
Err(err) => Err(err), Err(err) => Err(err),
} },
}).collect::<Result<Vec<_>, _>>()?.iter()) )
.collect::<Result<Vec<_>, _>>()?
.iter(),
),
), ),
Some(pending.mode), Some(pending.mode),
Some(pending.blob), Some(pending.blob),
)?; )?;
self self.fd
.fd
.atomic_commit( .atomic_commit(
&[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly], &[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly],
req, req,
@ -428,7 +439,11 @@ impl<A: AsRawFd + 'static> AtomicDrmSurface<A> {
*self.pending.read().unwrap() != *self.state.read().unwrap() *self.pending.read().unwrap() != *self.state.read().unwrap()
} }
pub fn commit<'a>(&self, framebuffers: impl Iterator<Item=&'a (framebuffer::Handle, plane::Handle)>, event: bool) -> Result<(), Error> { pub fn commit<'a>(
&self,
framebuffers: impl Iterator<Item = &'a (framebuffer::Handle, plane::Handle)>,
event: bool,
) -> Result<(), Error> {
if !self.active.load(Ordering::SeqCst) { if !self.active.load(Ordering::SeqCst) {
return Err(Error::DeviceInactive); return Err(Error::DeviceInactive);
} }
@ -538,7 +553,11 @@ impl<A: AsRawFd + 'static> AtomicDrmSurface<A> {
result result
} }
pub fn page_flip<'a>(&self, framebuffers: impl Iterator<Item=&'a (framebuffer::Handle, plane::Handle)>, event: bool) -> Result<(), Error> { pub fn page_flip<'a>(
&self,
framebuffers: impl Iterator<Item = &'a (framebuffer::Handle, plane::Handle)>,
event: bool,
) -> Result<(), Error> {
if !self.active.load(Ordering::SeqCst) { if !self.active.load(Ordering::SeqCst) {
return Err(Error::DeviceInactive); return Err(Error::DeviceInactive);
} }
@ -618,7 +637,13 @@ impl<A: AsRawFd + 'static> AtomicDrmSurface<A> {
Ok(result) Ok(result)
} }
pub fn test_plane_buffer(&self, fb: framebuffer::Handle, plane: plane::Handle, position: (i32, i32), size: (u32, u32)) -> Result<bool, Error> { pub fn test_plane_buffer(
&self,
fb: framebuffer::Handle,
plane: plane::Handle,
position: (i32, i32),
size: (u32, u32),
) -> Result<bool, Error> {
if !self.active.load(Ordering::SeqCst) { if !self.active.load(Ordering::SeqCst) {
return Err(Error::DeviceInactive); return Err(Error::DeviceInactive);
} }
@ -901,7 +926,8 @@ impl<A: AsRawFd + 'static> AtomicDrmSurface<A> {
property::Value::Framebuffer(None), property::Value::Framebuffer(None),
); );
let result = self.fd let result = self
.fd
.atomic_commit(&[AtomicCommitFlags::Nonblock], req) .atomic_commit(&[AtomicCommitFlags::Nonblock], req)
.map_err(|source| Error::Access { .map_err(|source| Error::Access {
errmsg: "Failed to commit on clear_plane", errmsg: "Failed to commit on clear_plane",
@ -910,7 +936,10 @@ impl<A: AsRawFd + 'static> AtomicDrmSurface<A> {
}); });
if result.is_ok() { if result.is_ok() {
self.additional_planes.lock().unwrap().retain(|info| info.handle != plane); self.additional_planes
.lock()
.unwrap()
.retain(|info| info.handle != plane);
} }
result result
@ -947,11 +976,17 @@ impl<A: AsRawFd + 'static> Drop for AtomicDrmSurface<A> {
// other ttys that use no cursor, might not clear it themselves. // other ttys that use no cursor, might not clear it themselves.
// This makes sure our cursor won't stay visible. // This makes sure our cursor won't stay visible.
if let Err(err) = self.clear_plane(self.plane) { if let Err(err) = self.clear_plane(self.plane) {
warn!(self.logger, "Failed to clear plane {:?} on {:?}: {}", self.plane, self.crtc, err); warn!(
self.logger,
"Failed to clear plane {:?} on {:?}: {}", self.plane, self.crtc, err
);
} }
for plane_info in self.additional_planes.lock().unwrap().iter() { for plane_info in self.additional_planes.lock().unwrap().iter() {
if let Err(err) = self.clear_plane(plane_info.handle) { if let Err(err) = self.clear_plane(plane_info.handle) {
warn!(self.logger, "Failed to clear plane {:?} on {:?}: {}", plane_info.handle, self.crtc, err); warn!(
self.logger,
"Failed to clear plane {:?} on {:?}: {}", plane_info.handle, self.crtc, err
);
} }
} }

View File

@ -11,12 +11,7 @@ use nix::libc::dev_t;
pub(super) mod atomic; pub(super) mod atomic;
pub(super) mod legacy; pub(super) mod legacy;
use super::{ use super::{device::DevPath, error::Error, plane_type, planes, PlaneType, Planes};
error::Error,
Planes, PlaneType,
plane_type, planes,
device::DevPath,
};
use crate::backend::allocator::{Format, Fourcc, Modifier}; use crate::backend::allocator::{Format, Fourcc, Modifier};
use atomic::AtomicDrmSurface; use atomic::AtomicDrmSurface;
use legacy::LegacyDrmSurface; use legacy::LegacyDrmSurface;
@ -159,7 +154,12 @@ impl<A: AsRawFd + 'static> DrmSurface<A> {
/// Fails if tests for the given plane fail, if the underlying /// Fails if tests for the given plane fail, if the underlying
/// implementation does not support the use of planes or if the plane /// implementation does not support the use of planes or if the plane
/// is not supported by this crtc. /// is not supported by this crtc.
pub fn use_plane(&self, plane: plane::Handle, position: (i32, i32), size: (u32, u32)) -> Result<(), Error> { pub fn use_plane(
&self,
plane: plane::Handle,
position: (i32, i32),
size: (u32, u32),
) -> Result<(), Error> {
match &*self.internal { match &*self.internal {
DrmSurfaceInternal::Atomic(surf) => surf.use_plane(plane, position, size), DrmSurfaceInternal::Atomic(surf) => surf.use_plane(plane, position, size),
DrmSurfaceInternal::Legacy(_) => Err(Error::NonPrimaryPlane(plane)), DrmSurfaceInternal::Legacy(_) => Err(Error::NonPrimaryPlane(plane)),
@ -200,17 +200,23 @@ impl<A: AsRawFd + 'static> DrmSurface<A> {
/// but will trigger a `vblank` event once done. /// but will trigger a `vblank` event once done.
/// Make sure to [set a `DeviceHandler`](crate::backend::drm::DrmDevice::set_handler) and /// Make sure to [set a `DeviceHandler`](crate::backend::drm::DrmDevice::set_handler) and
/// [register the belonging `Device`](crate::backend::drm::device_bind) before to receive the event in time. /// [register the belonging `Device`](crate::backend::drm::device_bind) before to receive the event in time.
pub fn commit<'a>(&self, mut framebuffers: impl Iterator<Item=&'a (framebuffer::Handle, plane::Handle)>, event: bool) -> Result<(), Error> { pub fn commit<'a>(
&self,
mut framebuffers: impl Iterator<Item = &'a (framebuffer::Handle, plane::Handle)>,
event: bool,
) -> Result<(), Error> {
match &*self.internal { match &*self.internal {
DrmSurfaceInternal::Atomic(surf) => surf.commit(framebuffers, event), DrmSurfaceInternal::Atomic(surf) => surf.commit(framebuffers, event),
DrmSurfaceInternal::Legacy(surf) => if let Some((fb, plane)) = framebuffers.next() { DrmSurfaceInternal::Legacy(surf) => {
if let Some((fb, plane)) = framebuffers.next() {
if plane_type(self, *plane)? != PlaneType::Primary { if plane_type(self, *plane)? != PlaneType::Primary {
return Err(Error::NonPrimaryPlane(*plane)); return Err(Error::NonPrimaryPlane(*plane));
} }
surf.commit(*fb, event) surf.commit(*fb, event)
} else { } else {
Ok(()) Ok(())
}, }
}
} }
} }
@ -222,17 +228,23 @@ impl<A: AsRawFd + 'static> DrmSurface<A> {
/// This operation is not blocking and will produce a `vblank` event once swapping is done. /// This operation is not blocking and will produce a `vblank` event once swapping is done.
/// Make sure to [set a `DeviceHandler`](crate::backend::drm::DrmDevice::set_handler) and /// Make sure to [set a `DeviceHandler`](crate::backend::drm::DrmDevice::set_handler) and
/// [register the belonging `DrmDevice`](crate::backend::drm::device_bind) before to receive the event in time. /// [register the belonging `DrmDevice`](crate::backend::drm::device_bind) before to receive the event in time.
pub fn page_flip<'a>(&self, mut framebuffers: impl Iterator<Item=&'a (framebuffer::Handle, plane::Handle)>, event: bool) -> Result<(), Error> { pub fn page_flip<'a>(
&self,
mut framebuffers: impl Iterator<Item = &'a (framebuffer::Handle, plane::Handle)>,
event: bool,
) -> Result<(), Error> {
match &*self.internal { match &*self.internal {
DrmSurfaceInternal::Atomic(surf) => surf.page_flip(framebuffers, event), DrmSurfaceInternal::Atomic(surf) => surf.page_flip(framebuffers, event),
DrmSurfaceInternal::Legacy(surf) => if let Some((fb, plane)) = framebuffers.next() { DrmSurfaceInternal::Legacy(surf) => {
if let Some((fb, plane)) = framebuffers.next() {
if plane_type(self, *plane)? != PlaneType::Primary { if plane_type(self, *plane)? != PlaneType::Primary {
return Err(Error::NonPrimaryPlane(*plane)); return Err(Error::NonPrimaryPlane(*plane));
} }
surf.page_flip(*fb, event) surf.page_flip(*fb, event)
} else { } else {
Ok(()) Ok(())
}, }
}
} }
} }
@ -416,8 +428,7 @@ impl<A: AsRawFd + 'static> DrmSurface<A> {
) -> Result<bool, Error> { ) -> Result<bool, Error> {
match &*self.internal { match &*self.internal {
DrmSurfaceInternal::Atomic(surf) => surf.test_plane_buffer(fb, plane, position, size), DrmSurfaceInternal::Atomic(surf) => surf.test_plane_buffer(fb, plane, position, size),
DrmSurfaceInternal::Legacy(_) => { Ok(false) } DrmSurfaceInternal::Legacy(_) => Ok(false), // There is no test-commiting with the legacy interface
// There is no test-commiting with the legacy interface
} }
} }

View File

@ -28,7 +28,7 @@ use crate::backend::egl::{
ffi::egl::{self as ffi_egl, types::EGLImage}, ffi::egl::{self as ffi_egl, types::EGLImage},
EGLContext, EGLSurface, Format as EGLFormat, MakeCurrentError, EGLContext, EGLSurface, Format as EGLFormat, MakeCurrentError,
}; };
use crate::{backend::SwapBuffersError}; use crate::backend::SwapBuffersError;
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
use crate::{ use crate::{
@ -538,7 +538,11 @@ impl Gles2Renderer {
let texture = Gles2Texture( let texture = Gles2Texture(
// why not store a `Gles2Texture`? because the user might do so. // why not store a `Gles2Texture`? because the user might do so.
// this is guaranteed a non-public internal type, so we are good. // this is guaranteed a non-public internal type, so we are good.
surface.user_data.get::<Rc<Gles2TextureInternal>>().cloned().unwrap_or_else(|| { surface
.user_data
.get::<Rc<Gles2TextureInternal>>()
.cloned()
.unwrap_or_else(|| {
let mut tex = 0; let mut tex = 0;
unsafe { self.gl.GenTextures(1, &mut tex) }; unsafe { self.gl.GenTextures(1, &mut tex) };
// new texture, upload in full // new texture, upload in full
@ -555,7 +559,7 @@ impl Gles2Renderer {
destruction_callback_sender: self.destruction_callback_sender.clone(), destruction_callback_sender: self.destruction_callback_sender.clone(),
}); });
texture texture
}) }),
); );
unsafe { unsafe {
@ -567,7 +571,6 @@ impl Gles2Renderer {
.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_T, ffi::CLAMP_TO_EDGE as i32); .TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_T, ffi::CLAMP_TO_EDGE as i32);
self.gl.PixelStorei(ffi::UNPACK_ROW_LENGTH, stride / pixelsize); self.gl.PixelStorei(ffi::UNPACK_ROW_LENGTH, stride / pixelsize);
if upload_full { if upload_full {
trace!(self.logger, "Uploading shm texture for {:?}", buffer); trace!(self.logger, "Uploading shm texture for {:?}", buffer);
self.gl.TexImage2D( self.gl.TexImage2D(
@ -659,7 +662,10 @@ impl Gles2Renderer {
} }
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
fn existing_dmabuf_texture(&self, buffer: &wl_buffer::WlBuffer) -> Result<Option<Gles2Texture>, Gles2Error> { fn existing_dmabuf_texture(
&self,
buffer: &wl_buffer::WlBuffer,
) -> Result<Option<Gles2Texture>, Gles2Error> {
let existing_texture = self let existing_texture = self
.dmabuf_cache .dmabuf_cache
.iter() .iter()
@ -945,10 +951,7 @@ impl Renderer for Gles2Renderer {
let texture = if egl.and_then(|egl| egl.egl_buffer_dimensions(&buffer)).is_some() { let texture = if egl.and_then(|egl| egl.egl_buffer_dimensions(&buffer)).is_some() {
self.import_egl(&buffer, egl.unwrap()) self.import_egl(&buffer, egl.unwrap())
} else if crate::wayland::shm::with_buffer_contents(&buffer, |_, _| ()).is_ok() { } else if crate::wayland::shm::with_buffer_contents(&buffer, |_, _| ()).is_ok() {
self.import_shm( self.import_shm(&buffer, surface)
&buffer,
surface,
)
} else { } else {
Err(Gles2Error::UnknownBufferType) Err(Gles2Error::UnknownBufferType)
}?; }?;
@ -973,12 +976,13 @@ impl Renderer for Gles2Renderer {
fn render<F, R>( fn render<F, R>(
&mut self, &mut self,
width: u32, height: u32, width: u32,
height: u32,
transform: Transform, transform: Transform,
rendering: F, rendering: F,
) -> Result<R, Self::Error> ) -> Result<R, Self::Error>
where where
F: FnOnce(&mut Self, &mut Self::Frame) -> R F: FnOnce(&mut Self, &mut Self::Frame) -> R,
{ {
self.make_current()?; self.make_current()?;
// delayed destruction until the next frame rendering. // delayed destruction until the next frame rendering.

View File

@ -10,11 +10,11 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::error::Error; use std::error::Error;
#[cfg(feature = "wayland_frontend")]
use crate::wayland::compositor::SurfaceAttributes;
use cgmath::{prelude::*, Matrix3, Vector2}; use cgmath::{prelude::*, Matrix3, Vector2};
#[cfg(feature = "wayland_frontend")] #[cfg(feature = "wayland_frontend")]
use wayland_server::protocol::{wl_buffer, wl_shm}; use wayland_server::protocol::{wl_buffer, wl_shm};
#[cfg(feature = "wayland_frontend")]
use crate::wayland::compositor::SurfaceAttributes;
use crate::{backend::SwapBuffersError, utils::Rectangle}; use crate::{backend::SwapBuffersError, utils::Rectangle};
#[cfg(feature = "renderer_gl")] #[cfg(feature = "renderer_gl")]
@ -262,8 +262,7 @@ pub trait Renderer {
rendering: F, rendering: F,
) -> Result<R, Self::Error> ) -> Result<R, Self::Error>
where where
F: FnOnce(&mut Self, &mut Self::Frame) -> R F: FnOnce(&mut Self, &mut Self::Frame) -> R;
;
} }
/// Returns the dimensions of a wl_buffer /// Returns the dimensions of a wl_buffer

View File

@ -10,10 +10,11 @@ use crate::backend::{
UnusedEvent, UnusedEvent,
}, },
renderer::{ renderer::{
gles2::{Gles2Error, Gles2Renderer, Gles2Frame, Gles2Texture}, gles2::{Gles2Error, Gles2Frame, Gles2Renderer, Gles2Texture},
Bind, Unbind, Frame, Renderer, Transform, Bind, Frame, Renderer, Transform, Unbind,
}, },
}; };
use crate::utils::Rectangle;
use std::{cell::RefCell, rc::Rc, time::Instant}; use std::{cell::RefCell, rc::Rc, time::Instant};
use wayland_egl as wegl; use wayland_egl as wegl;
use wayland_server::Display; use wayland_server::Display;
@ -28,7 +29,6 @@ use winit::{
platform::unix::WindowExtUnix, platform::unix::WindowExtUnix,
window::{Window as WinitWindow, WindowBuilder}, window::{Window as WinitWindow, WindowBuilder},
}; };
use crate::utils::Rectangle;
#[cfg(feature = "use_system_lib")] #[cfg(feature = "use_system_lib")]
use crate::backend::egl::display::EGLBufferReader; use crate::backend::egl::display::EGLBufferReader;
@ -264,7 +264,7 @@ impl WinitGraphicsBackend {
/// and this window set as the rendering target. /// and this window set as the rendering target.
pub fn render<F, R>(&mut self, rendering: F) -> Result<R, crate::backend::SwapBuffersError> pub fn render<F, R>(&mut self, rendering: F) -> Result<R, crate::backend::SwapBuffersError>
where where
F: FnOnce(&mut Gles2Renderer, &mut Gles2Frame) -> R F: FnOnce(&mut Gles2Renderer, &mut Gles2Frame) -> R,
{ {
let (width, height) = { let (width, height) = {
let size = self.size.borrow(); let size = self.size.borrow();
@ -272,7 +272,9 @@ impl WinitGraphicsBackend {
}; };
self.renderer.bind(self.egl.clone())?; self.renderer.bind(self.egl.clone())?;
let result = self.renderer.render(width, height, Transform::Normal, rendering)?; let result = self
.renderer
.render(width, height, Transform::Normal, rendering)?;
self.egl.swap_buffers()?; self.egl.swap_buffers()?;
self.renderer.unbind()?; self.renderer.unbind()?;
Ok(result) Ok(result)