diff --git a/anvil/src/buffer_utils.rs b/anvil/src/buffer_utils.rs index 9abf5ad..db91463 100644 --- a/anvil/src/buffer_utils.rs +++ b/anvil/src/buffer_utils.rs @@ -9,9 +9,7 @@ use smithay::reexports::nix::libc::dev_t; use std::collections::HashMap; #[cfg(feature = "egl")] -use smithay::backend::egl::{ - display::EGLBufferReader, BufferAccessError as EGLBufferAccessError, EGLBuffer, -}; +use smithay::backend::egl::{display::EGLBufferReader, BufferAccessError as EGLBufferAccessError, EGLBuffer}; use smithay::{ reexports::wayland_server::protocol::wl_buffer::WlBuffer, wayland::shm::{with_buffer_contents as shm_buffer_contents, BufferAccessError}, @@ -76,7 +74,7 @@ impl BufferUtils { let egl_buffer = match result { Ok(egl) => Some(egl), - Err(EGLBufferAccessError::NotManaged(_)) => { None }, + Err(EGLBufferAccessError::NotManaged(_)) => None, Err(err) => { error!(self.log, "EGL error"; "err" => format!("{:?}", err)); return Err(buffer); @@ -112,7 +110,7 @@ pub struct BufferTextures { #[cfg(feature = "udev")] impl BufferTextures { #[cfg(feature = "egl")] - pub fn load_texture<'a, R: Renderer>( + pub fn load_texture<'a, R: Renderer>( &'a mut self, id: u64, renderer: &mut R, @@ -136,7 +134,7 @@ impl BufferTextures { } #[cfg(not(feature = "egl"))] - pub fn load_texture<'a, R: Renderer>( + pub fn load_texture<'a, R: Renderer>( &'a mut self, id: u64, renderer: &mut R, @@ -149,14 +147,14 @@ impl BufferTextures { self.load_shm_texture(id, renderer, texture_destruction_callback) } - fn load_shm_texture<'a, R: Renderer>( + fn load_shm_texture<'a, R: Renderer>( &'a mut self, id: u64, renderer: &mut R, texture_destruction_callback: &Sender, ) -> Result<&'a T, R::Error> { let texture = renderer.import_shm(&self.buffer)?; - + if let Some(old_texture) = self.textures.insert(id, texture) { let _ = renderer.destroy_texture(old_texture)?; } @@ -173,4 +171,4 @@ impl Drop for BufferTextures { self.callbacks.get(&id).unwrap().send(texture).unwrap(); } } -} \ No newline at end of file +} diff --git a/anvil/src/drawing.rs b/anvil/src/drawing.rs index c5c5aef..8e04cc5 100644 --- a/anvil/src/drawing.rs +++ b/anvil/src/drawing.rs @@ -1,19 +1,12 @@ #![allow(clippy::too_many_arguments)] -use std::{ - cell::RefCell, - rc::Rc, - sync::mpsc::Sender, -}; +use std::{cell::RefCell, rc::Rc, sync::mpsc::Sender}; use slog::Logger; use smithay::{ + backend::renderer::{Renderer, Texture, Transform}, backend::SwapBuffersError, - backend::renderer::{Renderer, Transform, Texture}, - reexports::{ - calloop::LoopHandle, - wayland_server::protocol::wl_surface, - }, + reexports::{calloop::LoopHandle, wayland_server::protocol::wl_surface}, utils::Rectangle, wayland::{ compositor::{roles::Role, SubsurfaceRole, TraversalAction}, @@ -22,8 +15,8 @@ use smithay::{ }, }; +use crate::buffer_utils::{BufferTextures, BufferUtils}; use crate::shell::{MyCompositorToken, MyWindowMap, SurfaceData}; -use crate::buffer_utils::{BufferUtils, BufferTextures}; pub fn draw_cursor( renderer: &mut R, @@ -35,10 +28,10 @@ pub fn draw_cursor( token: MyCompositorToken, log: &Logger, ) -> Result<(), SwapBuffersError> - where - R: Renderer, - E: std::error::Error + Into, - T: Texture + 'static, +where + R: Renderer, + E: std::error::Error + Into, + T: Texture + 'static, { let (dx, dy) = match token.with_role_data::(surface, |data| data.hotspot) { Ok(h) => h, @@ -50,7 +43,16 @@ pub fn draw_cursor( (0, 0) } }; - draw_surface_tree(renderer, renderer_id, texture_destruction_callback, buffer_utils, surface, (x - dx, y - dy), token, log) + draw_surface_tree( + renderer, + renderer_id, + texture_destruction_callback, + buffer_utils, + surface, + (x - dx, y - dy), + token, + log, + ) } fn draw_surface_tree( @@ -63,10 +65,10 @@ fn draw_surface_tree( compositor_token: MyCompositorToken, log: &Logger, ) -> Result<(), SwapBuffersError> - where - R: Renderer, - E: std::error::Error + Into, - T: Texture + 'static, +where + R: Renderer, + E: std::error::Error + Into, + T: Texture + 'static, { let mut result = Ok(()); @@ -85,7 +87,7 @@ fn draw_surface_tree( // already logged the error Err(err) => { warn!(log, "Error loading buffer: {:?}", err); - }, + } }; } } @@ -133,15 +135,23 @@ fn draw_surface_tree( if let Some(ref data) = attributes.user_data.get::>() { let mut data = data.borrow_mut(); let (sub_x, sub_y) = data.current_state.sub_location; - if let Some(buffer_textures) = data.texture.as_mut().and_then(|x| x.downcast_mut::>()) { + if let Some(buffer_textures) = data + .texture + .as_mut() + .and_then(|x| x.downcast_mut::>()) + { // we need to re-extract the subsurface offset, as the previous closure // only passes it to our children if Role::::has(role) { x += sub_x; y += sub_y; } - let texture = buffer_textures.load_texture(renderer_id, renderer, texture_destruction_callback).unwrap(); - if let Err(err) = renderer.render_texture_at(texture, (x, y), Transform::Normal /* TODO */, 1.0) { + let texture = buffer_textures + .load_texture(renderer_id, renderer, texture_destruction_callback) + .unwrap(); + if let Err(err) = + renderer.render_texture_at(texture, (x, y), Transform::Normal /* TODO */, 1.0) + { result = Err(err.into()); } } @@ -163,41 +173,39 @@ pub fn draw_windows( compositor_token: MyCompositorToken, log: &::slog::Logger, ) -> Result<(), SwapBuffersError> - where - R: Renderer, - E: std::error::Error + Into, - T: Texture + 'static, +where + R: Renderer, + E: std::error::Error + Into, + T: Texture + 'static, { let mut result = Ok(()); // redraw the frame, in a simple but inneficient way - window_map.with_windows_from_bottom_to_top( - |toplevel_surface, mut initial_place, bounding_box| { - // skip windows that do not overlap with a given output - if let Some(output) = output_rect { - if !output.overlaps(bounding_box) { - return; - } - initial_place.0 -= output.x; + window_map.with_windows_from_bottom_to_top(|toplevel_surface, mut initial_place, bounding_box| { + // skip windows that do not overlap with a given output + if let Some(output) = output_rect { + if !output.overlaps(bounding_box) { + return; } - if let Some(wl_surface) = toplevel_surface.get_surface() { - // this surface is a root of a subsurface tree that needs to be drawn - if let Err(err) = draw_surface_tree( - renderer, - renderer_id, - texture_destruction_callback, - buffer_utils, - &wl_surface, - initial_place, - compositor_token, - log, - ) { - result = Err(err); - } + initial_place.0 -= output.x; + } + if let Some(wl_surface) = toplevel_surface.get_surface() { + // this surface is a root of a subsurface tree that needs to be drawn + if let Err(err) = draw_surface_tree( + renderer, + renderer_id, + texture_destruction_callback, + buffer_utils, + &wl_surface, + initial_place, + compositor_token, + log, + ) { + result = Err(err); } - }, - ); - + } + }); + result } @@ -211,10 +219,10 @@ pub fn draw_dnd_icon( token: MyCompositorToken, log: &::slog::Logger, ) -> Result<(), SwapBuffersError> - where - R: Renderer, - E: std::error::Error + Into, - T: Texture + 'static, +where + R: Renderer, + E: std::error::Error + Into, + T: Texture + 'static, { if !token.has_role::(surface) { warn!( @@ -222,23 +230,37 @@ pub fn draw_dnd_icon( "Trying to display as a dnd icon a surface that does not have the DndIcon role." ); } - draw_surface_tree(renderer, renderer_id, texture_destruction_callback, buffer_utils, surface, (x, y), token, log) + draw_surface_tree( + renderer, + renderer_id, + texture_destruction_callback, + buffer_utils, + surface, + (x, y), + token, + log, + ) } pub fn schedule_initial_render( renderer: Rc>, evt_handle: &LoopHandle, logger: ::slog::Logger, -) -where - ::Error: Into +) where + ::Error: Into, { let result = { let mut renderer = renderer.borrow_mut(); // Does not matter if we render an empty frame - renderer.begin(1, 1, Transform::Normal).map_err(Into::::into) - .and_then(|_| renderer.clear([0.8, 0.8, 0.9, 1.0]).map_err(Into::::into)) - .and_then(|_| renderer.finish()) + renderer + .begin(1, 1, Transform::Normal) + .map_err(Into::::into) + .and_then(|_| { + renderer + .clear([0.8, 0.8, 0.9, 1.0]) + .map_err(Into::::into) + }) + .and_then(|_| renderer.finish()) }; if let Err(err) = result { match err { diff --git a/anvil/src/udev.rs b/anvil/src/udev.rs index 27651b6..8272c83 100644 --- a/anvil/src/udev.rs +++ b/anvil/src/udev.rs @@ -5,7 +5,7 @@ use std::{ os::unix::io::{AsRawFd, RawFd}, path::PathBuf, rc::Rc, - sync::{atomic::Ordering, Arc, Mutex, mpsc}, + sync::{atomic::Ordering, mpsc, Arc, Mutex}, time::Duration, }; @@ -14,27 +14,16 @@ use slog::Logger; use smithay::{ backend::{ - SwapBuffersError, - drm::{ - DrmDevice, - DeviceHandler, - device_bind, - DrmRenderSurface, - DrmError, - DevPath, - }, - egl::{EGLDisplay, EGLContext, display::EGLBufferReader}, - renderer::{ - Transform, - Renderer, - gles2::{ - Gles2Renderer, - Gles2Texture, - }, - }, + drm::{device_bind, DevPath, DeviceHandler, DrmDevice, DrmError, DrmRenderSurface}, + egl::{display::EGLBufferReader, EGLContext, EGLDisplay}, libinput::{LibinputInputBackend, LibinputSessionInterface}, + renderer::{ + gles2::{Gles2Renderer, Gles2Texture}, + Renderer, Transform, + }, session::{auto::AutoSession, Session, Signal as SessionSignal}, udev::{primary_gpu, UdevBackend, UdevEvent}, + SwapBuffersError, }, reexports::{ calloop::{ @@ -45,16 +34,13 @@ use smithay::{ drm::{ self, control::{ - Device as ControlDevice, connector::{Info as ConnectorInfo, State as ConnectorState}, crtc, encoder::Info as EncoderInfo, + Device as ControlDevice, }, }, - gbm::{ - BufferObject as GbmBuffer, - Device as GbmDevice, - }, + gbm::{BufferObject as GbmBuffer, Device as GbmDevice}, input::Libinput, nix::{fcntl::OFlag, sys::stat::dev_t}, wayland_server::{ @@ -72,9 +58,9 @@ use smithay::{ }; use crate::buffer_utils::BufferUtils; +use crate::drawing::*; use crate::shell::{MyWindowMap, Roles}; use crate::state::AnvilState; -use crate::drawing::*; #[derive(Clone)] pub struct SessionFd(RawFd); @@ -358,7 +344,9 @@ impl UdevHandlerImpl { }; if let Entry::Vacant(entry) = backends.entry(crtc) { - info!(logger, "Trying to setup connector {:?}-{} with crtc {:?}", + info!( + logger, + "Trying to setup connector {:?}-{} with crtc {:?}", connector_info.interface(), connector_info.interface_id(), crtc, @@ -377,25 +365,26 @@ impl UdevHandlerImpl { continue; } }; - let surface = match device.create_surface(crtc, primary, connector_info.modes()[0], &[connector_info.handle()]) { + let surface = match device.create_surface( + crtc, + primary, + 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; - } - }; + 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, @@ -430,38 +419,40 @@ impl UdevHandlerImpl { match { let fd = SessionFd(fd); ( - DrmDevice::new( - fd.clone(), - true, - self.logger.clone(), - ), - GbmDevice::new( - fd - ), + DrmDevice::new(fd.clone(), true, self.logger.clone()), + GbmDevice::new(fd), ) - } - { + } { (Ok(drm), Ok(gbm)) => Some((drm, gbm)), (Err(err), _) => { - warn!(self.logger, "Skipping device {:?}, because of drm error: {}", device_id, err); + warn!( + self.logger, + "Skipping device {:?}, because of drm error: {}", device_id, err + ); None - }, + } (_, Err(err)) => { // TODO try DumbBuffer allocator in this case - warn!(self.logger, "Skipping device {:?}, because of gbm error: {}", device_id, err); + warn!( + self.logger, + "Skipping device {:?}, because of gbm error: {}", device_id, err + ); None - }, + } } }) { let egl = match EGLDisplay::new(&gbm, self.logger.clone()) { Ok(display) => display, Err(err) => { - warn!(self.logger, "Skipping device {:?}, because of egl display error: {}", device_id, err); + warn!( + self.logger, + "Skipping device {:?}, because of egl display error: {}", device_id, err + ); return; } }; - + // init hardware acceleration on the primary gpu. #[cfg(feature = "egl")] { @@ -470,19 +461,21 @@ impl UdevHandlerImpl { self.logger, "Initializing EGL Hardware Acceleration via {:?}", path ); - *self.egl_buffer_reader.borrow_mut() = - egl.bind_wl_display(&*self.display.borrow()).ok(); + *self.egl_buffer_reader.borrow_mut() = egl.bind_wl_display(&*self.display.borrow()).ok(); } } let context = match EGLContext::new(&egl, self.logger.clone()) { Ok(context) => context, Err(err) => { - warn!(self.logger, "Skipping device {:?}, because of egl context error: {}", device_id, err); + warn!( + self.logger, + "Skipping device {:?}, because of egl context error: {}", device_id, err + ); return; } }; - + let backends = Rc::new(RefCell::new(UdevHandlerImpl::::scan_connectors( &mut device, &gbm, @@ -498,7 +491,9 @@ impl UdevHandlerImpl { let pointer_image = { let context = EGLContext::new_shared(&egl, &context, self.logger.clone()).unwrap(); let mut renderer = unsafe { Gles2Renderer::new(context, self.logger.clone()).unwrap() }; - renderer.import_bitmap(&self.pointer_image).expect("Failed to load pointer") + renderer + .import_bitmap(&self.pointer_image) + .expect("Failed to load pointer") }; // Set the handler. @@ -674,35 +669,34 @@ impl DrmRenderer { ) { if let Some(surface) = self.backends.borrow().get(&crtc) { let result = DrmRenderer::render_surface( - &mut *surface.borrow_mut(), - &self.texture_destruction_callback.0, - &self.buffer_utils, - self.device_id, - 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 + &mut *surface.borrow_mut(), + &self.texture_destruction_callback.0, + &self.buffer_utils, + self.device_id, + 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::(), - Some(&DrmError::DeviceInactive) | - Some(&DrmError::Access { - source: drm::SystemError::PermissionDenied, - .. - })) - } - SwapBuffersError::ContextLost(err) => panic!("Rendering loop lost: {}", err), - }; + let reschedule = match err { + SwapBuffersError::AlreadySwapped => false, + SwapBuffersError::TemporaryFailure(err) => !matches!( + err.downcast_ref::(), + Some(&DrmError::DeviceInactive) + | Some(&DrmError::Access { + source: drm::SystemError::PermissionDenied, + .. + }) + ), + SwapBuffersError::ContextLost(err) => panic!("Rendering loop lost: {}", err), + }; if reschedule { debug!(self.logger, "Rescheduling"); @@ -741,7 +735,7 @@ impl DrmRenderer { self.window_map .borrow() .send_frames(self.start_time.elapsed().as_millis() as u32); - + while let Ok(texture) = self.texture_destruction_callback.1.try_recv() { let _ = surface.borrow_mut().destroy_texture(texture); } @@ -809,7 +803,16 @@ impl DrmRenderer { { if let Some(ref wl_surface) = dnd_icon.as_ref() { if wl_surface.as_ref().is_alive() { - draw_dnd_icon(surface, device_id, texture_destruction_callback, buffer_utils, wl_surface, (ptr_x, ptr_y), *compositor_token, logger)?; + draw_dnd_icon( + surface, + device_id, + texture_destruction_callback, + buffer_utils, + wl_surface, + (ptr_x, ptr_y), + *compositor_token, + logger, + )?; } } } @@ -842,4 +845,4 @@ impl DrmRenderer { } surface.finish() } -} \ No newline at end of file +} diff --git a/anvil/src/winit.rs b/anvil/src/winit.rs index d7bd155..daecb36 100644 --- a/anvil/src/winit.rs +++ b/anvil/src/winit.rs @@ -3,7 +3,7 @@ use std::{cell::RefCell, rc::Rc, sync::atomic::Ordering, time::Duration}; //#[cfg(feature = "egl")] //use smithay::backend::egl::EGLGraphicsBackend; use smithay::{ - backend::{renderer::Renderer, input::InputBackend, winit, SwapBuffersError}, + backend::{input::InputBackend, renderer::Renderer, winit, SwapBuffersError}, reexports::{ calloop::EventLoop, wayland_server::{protocol::wl_output, Display}, @@ -16,9 +16,9 @@ use smithay::{ use slog::Logger; -use crate::state::AnvilState; use crate::buffer_utils::BufferUtils; use crate::drawing::*; +use crate::state::AnvilState; pub fn run_winit( display: Rc>, @@ -111,10 +111,22 @@ pub fn run_winit( // drawing logic { renderer.begin().expect("Failed to render frame"); - renderer.clear([0.8, 0.8, 0.9, 1.0]).expect("Failed to clear frame"); + renderer + .clear([0.8, 0.8, 0.9, 1.0]) + .expect("Failed to clear frame"); // draw the windows - draw_windows(&mut renderer, 0, &texture_send, &buffer_utils, &*state.window_map.borrow(), None, state.ctoken, &log).expect("Failed to renderer windows"); + draw_windows( + &mut renderer, + 0, + &texture_send, + &buffer_utils, + &*state.window_map.borrow(), + None, + state.ctoken, + &log, + ) + .expect("Failed to renderer windows"); let (x, y) = *state.pointer_location.borrow(); // draw the dnd icon if any @@ -122,7 +134,17 @@ pub fn run_winit( let guard = state.dnd_icon.lock().unwrap(); if let Some(ref surface) = *guard { if surface.as_ref().is_alive() { - draw_dnd_icon(&mut renderer, 0, &texture_send, &buffer_utils, surface, (x as i32, y as i32), state.ctoken, &log).expect("Failed to render dnd icon"); + draw_dnd_icon( + &mut renderer, + 0, + &texture_send, + &buffer_utils, + surface, + (x as i32, y as i32), + state.ctoken, + &log, + ) + .expect("Failed to render dnd icon"); } } } @@ -137,11 +159,21 @@ pub fn run_winit( if reset { *guard = CursorImageStatus::Default; } - + // draw as relevant if let CursorImageStatus::Image(ref surface) = *guard { renderer.window().set_cursor_visible(false); - draw_cursor(&mut renderer, 0, &texture_send, &buffer_utils, surface, (x as i32, y as i32), state.ctoken, &log).expect("Failed to render cursor"); + draw_cursor( + &mut renderer, + 0, + &texture_send, + &buffer_utils, + surface, + (x as i32, y as i32), + state.ctoken, + &log, + ) + .expect("Failed to render cursor"); } else { renderer.window().set_cursor_visible(true); } @@ -153,7 +185,6 @@ pub fn run_winit( } } - if event_loop .dispatch(Some(Duration::from_millis(16)), &mut state) .is_err() diff --git a/examples/raw_drm.rs b/examples/raw_drm.rs index 2e72b87..415944e 100644 --- a/examples/raw_drm.rs +++ b/examples/raw_drm.rs @@ -6,28 +6,18 @@ extern crate slog; use slog::Drain; use smithay::{ backend::{ - allocator::{Format, Fourcc, Modifier, Swapchain, Slot, dumb::DumbBuffer}, - drm::{ - DrmError, - DrmDevice, DrmSurface, - DeviceHandler, - device_bind, - } + allocator::{dumb::DumbBuffer, Format, Fourcc, Modifier, Slot, Swapchain}, + drm::{device_bind, DeviceHandler, DrmDevice, DrmError, DrmSurface}, }, reexports::{ calloop::EventLoop, - drm::{ - control::{ - connector::State as ConnectorState, crtc, framebuffer, - Device as ControlDevice, - }, - }, + drm::control::{connector::State as ConnectorState, crtc, framebuffer, Device as ControlDevice}, }, }; use std::{ fs::{File, OpenOptions}, - os::unix::io::{AsRawFd, RawFd}, io::Error as IoError, + os::unix::io::{AsRawFd, RawFd}, rc::Rc, sync::Mutex, }; @@ -54,10 +44,11 @@ fn main() { let mut options = OpenOptions::new(); options.read(true); options.write(true); - let fd = FdWrapper { file: Rc::new(options.open("/dev/dri/card0").unwrap()) }; + let fd = FdWrapper { + file: Rc::new(options.open("/dev/dri/card0").unwrap()), + }; - let mut device = - DrmDevice::new(fd.clone(), true, log.clone()).unwrap(); + let mut device = DrmDevice::new(fd.clone(), true, log.clone()).unwrap(); // Get a set of all modesetting resource handles (excluding planes): let res_handles = ControlDevice::resource_handles(&device).unwrap(); @@ -105,12 +96,20 @@ fn main() { */ let (w, h) = mode.size(); let allocator = DrmDevice::new(fd, false, log.clone()).unwrap(); - let mut swapchain = Swapchain::new(allocator, w.into(), h.into(), Format { code: Fourcc::Argb8888, modifier: Modifier::Invalid }); + let mut swapchain = Swapchain::new( + allocator, + w.into(), + h.into(), + Format { + code: Fourcc::Argb8888, + modifier: Modifier::Invalid, + }, + ); let first_buffer: Slot, _> = swapchain.acquire().unwrap().unwrap(); let framebuffer = surface.add_framebuffer(&first_buffer.handle, 32, 32).unwrap(); first_buffer.set_userdata(framebuffer); - // Get the device as an allocator into the + // Get the device as an allocator into the device.set_handler(DrmHandlerImpl { swapchain, current: first_buffer, @@ -133,7 +132,8 @@ fn main() { } pub struct DrmHandlerImpl { - swapchain: Swapchain, DumbBuffer, framebuffer::Handle, DumbBuffer>, + swapchain: + Swapchain, DumbBuffer, framebuffer::Handle, DumbBuffer>, current: Slot, framebuffer::Handle>, surface: Rc>, } diff --git a/src/backend/allocator/dmabuf.rs b/src/backend/allocator/dmabuf.rs index 142f3a6..d5fdd49 100644 --- a/src/backend/allocator/dmabuf.rs +++ b/src/backend/allocator/dmabuf.rs @@ -1,6 +1,6 @@ use super::{Buffer, Format, Modifier}; -use std::sync::{Arc, Weak}; use std::os::unix::io::RawFd; +use std::sync::{Arc, Weak}; const MAX_PLANES: usize = 4; @@ -68,9 +68,11 @@ impl Dmabuf { fds: &[RawFd], ) -> Option { if offsets.len() < planes - || strides.len() < planes - || fds.len() < planes - || planes == 0 || planes > MAX_PLANES { + || strides.len() < planes + || fds.len() < planes + || planes == 0 + || planes > MAX_PLANES + { return None; } @@ -82,9 +84,24 @@ impl Dmabuf { Some(Dmabuf(Arc::new(DmabufInternal { num_planes: planes, - offsets: [*offsets.next().unwrap(), *offsets.next().unwrap(), *offsets.next().unwrap(), *offsets.next().unwrap()], - strides: [*strides.next().unwrap(), *strides.next().unwrap(), *strides.next().unwrap(), *strides.next().unwrap()], - fds: [*fds.next().unwrap(), *fds.next().unwrap(), *fds.next().unwrap(), *fds.next().unwrap()], + offsets: [ + *offsets.next().unwrap(), + *offsets.next().unwrap(), + *offsets.next().unwrap(), + *offsets.next().unwrap(), + ], + strides: [ + *strides.next().unwrap(), + *strides.next().unwrap(), + *strides.next().unwrap(), + *strides.next().unwrap(), + ], + fds: [ + *fds.next().unwrap(), + *fds.next().unwrap(), + *fds.next().unwrap(), + *fds.next().unwrap(), + ], width: src.width(), height: src.height(), @@ -105,8 +122,7 @@ impl Dmabuf { } pub fn has_modifier(&self) -> bool { - self.0.format.modifier != Modifier::Invalid && - self.0.format.modifier != Modifier::Linear + self.0.format.modifier != Modifier::Invalid && self.0.format.modifier != Modifier::Linear } pub fn weak(&self) -> WeakDmabuf { @@ -128,4 +144,4 @@ impl Drop for DmabufInternal { } } } -} \ No newline at end of file +} diff --git a/src/backend/allocator/dumb.rs b/src/backend/allocator/dumb.rs index 25db611..f166662 100644 --- a/src/backend/allocator/dumb.rs +++ b/src/backend/allocator/dumb.rs @@ -2,7 +2,7 @@ use std::os::unix::io::AsRawFd; use std::sync::Arc; use drm::buffer::Buffer as DrmBuffer; -use drm::control::{Device as ControlDevice, dumbbuffer::DumbBuffer as Handle}; +use drm::control::{dumbbuffer::DumbBuffer as Handle, Device as ControlDevice}; use super::{Allocator, Buffer, Format}; use crate::backend::drm::device::{DrmDevice, DrmDeviceInternal, FdWrapper}; @@ -16,8 +16,13 @@ pub struct DumbBuffer { impl Allocator> for DrmDevice { type Error = drm::SystemError; - fn create_buffer(&mut self, width: u32, height: u32, format: Format) -> Result, Self::Error> { - let handle = self.create_dumb_buffer((width, height), format.code, 32/* TODO */)?; + fn create_buffer( + &mut self, + width: u32, + height: u32, + format: Format, + ) -> Result, Self::Error> { + let handle = self.create_dumb_buffer((width, height), format.code, 32 /* TODO */)?; Ok(DumbBuffer { fd: match &*self.internal { @@ -38,7 +43,7 @@ impl Buffer for DumbBuffer { fn height(&self) -> u32 { self.handle.size().1 } - + fn format(&self) -> Format { self.format } @@ -48,4 +53,4 @@ impl Drop for DumbBuffer { fn drop(&mut self) { let _ = self.fd.destroy_dumb_buffer(self.handle); } -} \ No newline at end of file +} diff --git a/src/backend/allocator/gbm.rs b/src/backend/allocator/gbm.rs index 8b878f8..70c6d87 100644 --- a/src/backend/allocator/gbm.rs +++ b/src/backend/allocator/gbm.rs @@ -1,6 +1,6 @@ +use super::{dmabuf::Dmabuf, Allocator, Buffer, Format, Fourcc, Modifier}; +use gbm::{BufferObject as GbmBuffer, BufferObjectFlags, Device as GbmDevice}; use std::os::unix::io::AsRawFd; -use gbm::{BufferObject as GbmBuffer, Device as GbmDevice, BufferObjectFlags}; -use super::{Allocator, Buffer, Format, Fourcc, Modifier, dmabuf::Dmabuf}; impl Allocator> for GbmDevice { type Error = std::io::Error; @@ -13,7 +13,12 @@ impl Allocator> for GbmDevice { } self.create_buffer_object(width, height, format.code, usage) } else { - self.create_buffer_object_with_modifiers(width, height, format.code, Some(format.modifier).into_iter()) + self.create_buffer_object_with_modifiers( + width, + height, + format.code, + Some(format.modifier).into_iter(), + ) } } } @@ -77,15 +82,23 @@ impl std::convert::TryFrom> for Dmabuf { return Err(GbmConvertError::InvalidFD); } - let offsets = (0i32..planes).map(|i| buf.offset(i)).collect::, gbm::DeviceDestroyedError>>()?; - let strides = (0i32..planes).map(|i| buf.stride_for_plane(i)).collect::, gbm::DeviceDestroyedError>>()?; + let offsets = (0i32..planes) + .map(|i| buf.offset(i)) + .collect::, gbm::DeviceDestroyedError>>()?; + let strides = (0i32..planes) + .map(|i| buf.stride_for_plane(i)) + .collect::, gbm::DeviceDestroyedError>>()?; Ok(Dmabuf::new(buf, planes as usize, &offsets, &strides, &fds).unwrap()) } } impl Dmabuf { - pub fn import(&self, gbm: &GbmDevice, usage: BufferObjectFlags) -> std::io::Result> { + pub fn import( + &self, + gbm: &GbmDevice, + usage: BufferObjectFlags, + ) -> std::io::Result> { let buf = &*self.0; if self.has_modifier() || buf.num_planes > 1 || buf.offsets[0] != 0 { gbm.import_buffer_object_from_dma_buf_with_modifiers( @@ -106,8 +119,12 @@ impl Dmabuf { buf.height, buf.strides[0], buf.format.code, - if buf.format.modifier == Modifier::Linear { usage | BufferObjectFlags::LINEAR } else { usage }, + if buf.format.modifier == Modifier::Linear { + usage | BufferObjectFlags::LINEAR + } else { + usage + }, ) } } -} \ No newline at end of file +} diff --git a/src/backend/allocator/mod.rs b/src/backend/allocator/mod.rs index 9a2f467..c543e42 100644 --- a/src/backend/allocator/mod.rs +++ b/src/backend/allocator/mod.rs @@ -1,18 +1,23 @@ -#[cfg(feature = "backend_gbm")] -pub mod gbm; +pub mod dmabuf; #[cfg(feature = "backend_drm")] pub mod dumb; -pub mod dmabuf; +#[cfg(feature = "backend_gbm")] +pub mod gbm; mod swapchain; pub use swapchain::{Slot, Swapchain, SwapchainError}; -pub use drm_fourcc::{DrmFormat as Format, DrmFourcc as Fourcc, DrmModifier as Modifier, DrmVendor as Vendor, UnrecognizedFourcc, UnrecognizedVendor}; +pub use drm_fourcc::{ + DrmFormat as Format, DrmFourcc as Fourcc, DrmModifier as Modifier, DrmVendor as Vendor, + UnrecognizedFourcc, UnrecognizedVendor, +}; pub trait Buffer { fn width(&self) -> u32; fn height(&self) -> u32; - fn size(&self) -> (u32, u32) { (self.width(), self.height()) } + fn size(&self) -> (u32, u32) { + (self.width(), self.height()) + } fn format(&self) -> Format; } @@ -20,4 +25,4 @@ pub trait Allocator { type Error: std::error::Error; fn create_buffer(&mut self, width: u32, height: u32, format: Format) -> Result; -} \ No newline at end of file +} diff --git a/src/backend/allocator/swapchain.rs b/src/backend/allocator/swapchain.rs index 0232c7a..cca4bb1 100644 --- a/src/backend/allocator/swapchain.rs +++ b/src/backend/allocator/swapchain.rs @@ -1,6 +1,9 @@ use std::convert::TryInto; -use std::sync::{Arc, Mutex, MutexGuard, atomic::{AtomicBool, Ordering}}; use std::ops::Deref; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Mutex, MutexGuard, +}; use crate::backend::allocator::{Allocator, Buffer, Format}; @@ -84,12 +87,12 @@ where impl Swapchain where - A: Allocator, - B: Buffer + TryInto, + A: Allocator, + B: Buffer + TryInto, D: Buffer, E1: std::error::Error + 'static, E2: std::error::Error + 'static, - U: 'static + U: 'static, { pub fn new(allocator: A, width: u32, height: u32, format: Format) -> Swapchain { Swapchain { @@ -107,8 +110,10 @@ where if free_slot.buffer.is_none() { free_slot.buffer = Arc::new(Some( self.allocator - .create_buffer(self.width, self.height, self.format).map_err(SwapchainError::AllocationError)? - .try_into().map_err(SwapchainError::ConversionError)? + .create_buffer(self.width, self.height, self.format) + .map_err(SwapchainError::AllocationError)? + .try_into() + .map_err(SwapchainError::ConversionError)?, )); } assert!(free_slot.buffer.is_some()); @@ -116,7 +121,6 @@ where if !free_slot.acquired.swap(true, Ordering::SeqCst) { return Ok(Some(free_slot.clone())); } - } // no free slots @@ -132,4 +136,4 @@ where self.height = height; self.slots = Default::default(); } -} \ No newline at end of file +} diff --git a/src/backend/drm/device/atomic.rs b/src/backend/drm/device/atomic.rs index 3448dc9..9dca352 100644 --- a/src/backend/drm/device/atomic.rs +++ b/src/backend/drm/device/atomic.rs @@ -1,9 +1,15 @@ use std::collections::HashMap; -use std::sync::{Arc, atomic::{AtomicBool, Ordering}}; use std::os::unix::io::AsRawFd; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; use drm::control::atomic::AtomicModeReq; -use drm::control::{Device as ControlDevice, AtomicCommitFlags, PropertyValueSet, ResourceHandle, crtc, connector, framebuffer, plane, property}; +use drm::control::{ + connector, crtc, framebuffer, plane, property, AtomicCommitFlags, Device as ControlDevice, + PropertyValueSet, ResourceHandle, +}; use super::{DevPath, FdWrapper}; use crate::backend::drm::error::Error; @@ -31,8 +37,12 @@ pub struct AtomicDrmDevice { } impl AtomicDrmDevice { - pub fn new(fd: Arc>, active: Arc, disable_connectors: bool, logger: ::slog::Logger) -> Result - { + pub fn new( + fd: Arc>, + active: Arc, + disable_connectors: bool, + logger: ::slog::Logger, + ) -> Result { let mut dev = AtomicDrmDevice { fd, active, @@ -42,17 +52,16 @@ impl AtomicDrmDevice { }; // Enumerate (and save) the current device state. - let res_handles = dev.fd.resource_handles() - .map_err(|source| Error::Access { - errmsg: "Error loading drm resources", - dev: dev.fd.dev_path(), - source, - })?; + let res_handles = dev.fd.resource_handles().map_err(|source| Error::Access { + errmsg: "Error loading drm resources", + dev: dev.fd.dev_path(), + source, + })?; let plane_handles = dev.fd.plane_handles().map_err(|source| Error::Access { errmsg: "Error loading planes", dev: dev.fd.dev_path(), - source + source, })?; let planes = plane_handles.planes(); @@ -77,7 +86,7 @@ impl AtomicDrmDevice { dev.old_state = old_state; dev.prop_mapping = mapping; trace!(dev.logger, "Mapping: {:#?}", dev.prop_mapping); - + // If the user does not explicitly requests us to skip this, // we clear out the complete connector<->crtc mapping on device creation. // @@ -167,12 +176,11 @@ impl AtomicDrmDevice { // on top of the state the previous compositor left the device in. // This is because we do commits per surface and not per device, so we do a global // commit here, to fix any conflicts. - let res_handles = self.fd.resource_handles() - .map_err(|source| Error::Access { - errmsg: "Error loading drm resources", - dev: self.fd.dev_path(), - source, - })?; + let res_handles = self.fd.resource_handles().map_err(|source| Error::Access { + errmsg: "Error loading drm resources", + dev: self.fd.dev_path(), + source, + })?; // Disable all connectors (otherwise we might run into conflicting commits when restarting the rendering loop) let mut req = AtomicModeReq::new(); @@ -206,13 +214,14 @@ impl AtomicDrmDevice { req.add_property(*crtc, *active_prop, property::Value::Boolean(false)); req.add_property(*crtc, *mode_prop, property::Value::Unknown(0)); } - self.fd.atomic_commit(&[AtomicCommitFlags::AllowModeset], req) + self.fd + .atomic_commit(&[AtomicCommitFlags::AllowModeset], req) .map_err(|source| Error::Access { errmsg: "Failed to disable connectors", dev: self.fd.dev_path(), source, })?; - + Ok(()) } } diff --git a/src/backend/drm/device/legacy.rs b/src/backend/drm/device/legacy.rs index d78f955..edf9143 100644 --- a/src/backend/drm/device/legacy.rs +++ b/src/backend/drm/device/legacy.rs @@ -1,8 +1,11 @@ use std::collections::HashMap; -use std::sync::{Arc, atomic::{AtomicBool, Ordering}}; use std::os::unix::io::AsRawFd; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; -use drm::control::{Device as ControlDevice, crtc, connector}; +use drm::control::{connector, crtc, Device as ControlDevice}; use super::{DevPath, FdWrapper}; use crate::backend::drm::error::Error; @@ -15,24 +18,27 @@ pub struct LegacyDrmDevice { } impl LegacyDrmDevice { - pub fn new(fd: Arc>, active: Arc, disable_connectors: bool, logger: slog::Logger) -> Result - { + pub fn new( + fd: Arc>, + active: Arc, + disable_connectors: bool, + logger: slog::Logger, + ) -> Result { let mut dev = LegacyDrmDevice { fd, active, old_state: HashMap::new(), logger: logger.new(o!("smithay_module" => "backend_drm_legacy", "drm_module" => "device")), }; - + // Enumerate (and save) the current device state. // We need to keep the previous device configuration to restore the state later, // so we query everything, that we can set. - let res_handles = dev.fd.resource_handles() - .map_err(|source| Error::Access { - errmsg: "Error loading drm resources", - dev: dev.fd.dev_path(), - source, - })?; + let res_handles = dev.fd.resource_handles().map_err(|source| Error::Access { + errmsg: "Error loading drm resources", + dev: dev.fd.dev_path(), + source, + })?; for &con in res_handles.connectors() { let con_info = dev.fd.get_connector(con).map_err(|source| Error::Access { errmsg: "Error loading connector info", @@ -60,7 +66,6 @@ impl LegacyDrmDevice { } } - // If the user does not explicitly requests us to skip this, // we clear out the complete connector<->crtc mapping on device creation. // @@ -83,17 +88,18 @@ impl LegacyDrmDevice { })?; set_connector_state(&*self.fd, res_handles.connectors().iter().copied(), false)?; - for crtc in res_handles.crtcs() { - // null commit (necessary to trigger removal on the kernel side with the legacy api.) - self.fd.set_crtc(*crtc, None, (0, 0), &[], None) - .map_err(|source| Error::Access { - errmsg: "Error setting crtc", - dev: self.fd.dev_path(), - source, - })?; - } + for crtc in res_handles.crtcs() { + // null commit (necessary to trigger removal on the kernel side with the legacy api.) + self.fd + .set_crtc(*crtc, None, (0, 0), &[], None) + .map_err(|source| Error::Access { + errmsg: "Error setting crtc", + dev: self.fd.dev_path(), + source, + })?; + } - Ok(()) + Ok(()) } } @@ -127,38 +133,32 @@ pub fn set_connector_state( enabled: bool, ) -> Result<(), Error> where - D: ControlDevice + D: ControlDevice, { // for every connector... for conn in connectors { - let info = dev - .get_connector(conn) - .map_err(|source| Error::Access { - errmsg: "Failed to get connector infos", - dev: dev.dev_path(), - source, - })?; + let info = dev.get_connector(conn).map_err(|source| Error::Access { + errmsg: "Failed to get connector infos", + dev: dev.dev_path(), + source, + })?; // that is currently connected ... if info.state() == connector::State::Connected { // get a list of it's properties. - let props = dev - .get_properties(conn) - .map_err(|source| Error::Access { - errmsg: "Failed to get properties for connector", - dev: dev.dev_path(), - source, - })?; + let props = dev.get_properties(conn).map_err(|source| Error::Access { + errmsg: "Failed to get properties for connector", + dev: dev.dev_path(), + source, + })?; let (handles, _) = props.as_props_and_values(); // for every handle ... for handle in handles { // get information of that property - let info = dev - .get_property(*handle) - .map_err(|source| Error::Access { - errmsg: "Failed to get property of connector", - dev: dev.dev_path(), - source, - })?; + let info = dev.get_property(*handle).map_err(|source| Error::Access { + errmsg: "Failed to get property of connector", + dev: dev.dev_path(), + source, + })?; // to find out, if we got the handle of the "DPMS" property ... if info.name().to_str().map(|x| x == "DPMS").unwrap_or(false) { // so we can use that to turn on / off the connector @@ -181,4 +181,4 @@ where } } Ok(()) -} \ No newline at end of file +} diff --git a/src/backend/drm/device/mod.rs b/src/backend/drm/device/mod.rs index 55bf9a3..59de70d 100644 --- a/src/backend/drm/device/mod.rs +++ b/src/backend/drm/device/mod.rs @@ -1,24 +1,27 @@ -use std::rc::Rc; use std::cell::RefCell; use std::collections::HashSet; use std::convert::TryFrom; -use std::sync::{Arc, atomic::AtomicBool}; -use std::path::PathBuf; use std::os::unix::io::{AsRawFd, RawFd}; +use std::path::PathBuf; +use std::rc::Rc; +use std::sync::{atomic::AtomicBool, Arc}; use calloop::{generic::Generic, InsertError, LoopHandle, Source}; -use drm::{Device as BasicDevice, ClientCapability, DriverCapability}; -use drm::control::{ResourceHandles, PlaneResourceHandles, Device as ControlDevice, Event, Mode, PlaneType, crtc, plane, connector, property}; +use drm::control::{ + connector, crtc, plane, property, Device as ControlDevice, Event, Mode, PlaneResourceHandles, PlaneType, + ResourceHandles, +}; +use drm::{ClientCapability, Device as BasicDevice, DriverCapability}; use nix::libc::dev_t; use nix::sys::stat::fstat; pub(super) mod atomic; pub(super) mod legacy; +use super::error::Error; +use super::surface::{atomic::AtomicDrmSurface, legacy::LegacyDrmSurface, DrmSurface, DrmSurfaceInternal}; +use crate::backend::allocator::{Format, Fourcc, Modifier}; use atomic::AtomicDrmDevice; use legacy::LegacyDrmDevice; -use super::surface::{DrmSurface, DrmSurfaceInternal, atomic::AtomicDrmSurface, legacy::LegacyDrmSurface}; -use super::error::Error; -use crate::backend::allocator::{Fourcc, Format, Modifier}; pub struct DrmDevice { pub(super) dev_id: dev_t, @@ -91,10 +94,8 @@ impl DrmDevice { { let log = crate::slog_or_fallback(logger).new(o!("smithay_module" => "backend_drm")); info!(log, "DrmDevice initializing"); - - let dev_id = fstat(fd.as_raw_fd()) - .map_err(Error::UnableToGetDeviceId)? - .st_rdev; + + let dev_id = fstat(fd.as_raw_fd()).map_err(Error::UnableToGetDeviceId)?.st_rdev; let active = Arc::new(AtomicBool::new(true)); let dev = Arc::new({ let mut dev = FdWrapper { @@ -115,7 +116,9 @@ impl DrmDevice { dev }); - let has_universal_planes = dev.set_client_capability(ClientCapability::UniversalPlanes, true).is_ok(); + let has_universal_planes = dev + .set_client_capability(ClientCapability::UniversalPlanes, true) + .is_ok(); let resources = dev.resource_handles().map_err(|source| Error::Access { errmsg: "Error loading resource handles", dev: dev.dev_path(), @@ -126,7 +129,12 @@ impl DrmDevice { dev: dev.dev_path(), source, })?; - let internal = Arc::new(DrmDevice::create_internal(dev, active, disable_connectors, log.clone())?); + let internal = Arc::new(DrmDevice::create_internal( + dev, + active, + disable_connectors, + log.clone(), + )?); Ok(DrmDevice { dev_id, @@ -141,7 +149,12 @@ impl DrmDevice { }) } - fn create_internal(dev: Arc>, active: Arc, disable_connectors: bool, log: ::slog::Logger) -> Result, Error> { + fn create_internal( + dev: Arc>, + active: Arc, + disable_connectors: bool, + log: ::slog::Logger, + ) -> Result, Error> { let force_legacy = std::env::var("SMITHAY_USE_LEGACY") .map(|x| { x == "1" || x.to_lowercase() == "true" || x.to_lowercase() == "yes" || x.to_lowercase() == "y" @@ -151,13 +164,15 @@ impl DrmDevice { if force_legacy { info!(log, "SMITHAY_USE_LEGACY is set. Forcing LegacyDrmDevice."); }; - - Ok(if dev.set_client_capability(ClientCapability::Atomic, true).is_ok() && !force_legacy { - DrmDeviceInternal::Atomic(AtomicDrmDevice::new(dev, active, disable_connectors, log)?) - } else { - info!(log, "Falling back to LegacyDrmDevice"); - DrmDeviceInternal::Legacy(LegacyDrmDevice::new(dev, active, disable_connectors, log)?) - }) + + Ok( + if dev.set_client_capability(ClientCapability::Atomic, true).is_ok() && !force_legacy { + DrmDeviceInternal::Atomic(AtomicDrmDevice::new(dev, active, disable_connectors, log)?) + } else { + info!(log, "Falling back to LegacyDrmDevice"); + DrmDeviceInternal::Legacy(LegacyDrmDevice::new(dev, active, disable_connectors, log)?) + }, + ) } pub fn process_events(&mut self) { @@ -196,7 +211,7 @@ impl DrmDevice { DrmDeviceInternal::Legacy(_) => false, } } - + pub fn set_handler(&mut self, handler: impl DeviceHandler + 'static) { let handler = Some(Box::new(handler) as Box); *self.handler.borrow_mut() = handler; @@ -219,14 +234,20 @@ impl DrmDevice { let info = self.get_plane(*plane).map_err(|source| Error::Access { errmsg: "Failed to get plane information", dev: self.dev_path(), - source, + source, })?; let filter = info.possible_crtcs(); if self.resources.filter_crtcs(filter).contains(crtc) { match self.plane_type(*plane)? { - PlaneType::Primary => { primary = Some(*plane); }, - PlaneType::Cursor => { cursor = Some(*plane); }, - PlaneType::Overlay => { overlay.push(*plane); }, + PlaneType::Primary => { + primary = Some(*plane); + } + PlaneType::Cursor => { + cursor = Some(*plane); + } + PlaneType::Overlay => { + overlay.push(*plane); + } }; } } @@ -234,7 +255,11 @@ impl DrmDevice { Ok(Planes { primary: primary.expect("Crtc has no primary plane"), cursor, - overlay: if self.has_universal_planes { Some(overlay) } else { None }, + overlay: if self.has_universal_planes { + Some(overlay) + } else { + None + }, }) } @@ -242,14 +267,14 @@ impl DrmDevice { let props = self.get_properties(plane).map_err(|source| Error::Access { errmsg: "Failed to get properties of plane", dev: self.dev_path(), - source, + source, })?; let (ids, vals) = props.as_props_and_values(); for (&id, &val) in ids.iter().zip(vals.iter()) { let info = self.get_property(id).map_err(|source| Error::Access { errmsg: "Failed to get property info", dev: self.dev_path(), - source, + source, })?; if info.name().to_str().map(|x| x == "type").unwrap_or(false) { return Ok(match val { @@ -262,21 +287,27 @@ impl DrmDevice { unreachable!() } - pub fn create_surface(&self, crtc: crtc::Handle, plane: plane::Handle, mode: Mode, connectors: &[connector::Handle]) -> Result, Error> { + pub fn create_surface( + &self, + crtc: crtc::Handle, + plane: plane::Handle, + mode: Mode, + connectors: &[connector::Handle], + ) -> Result, Error> { if connectors.is_empty() { return Err(Error::SurfaceWithoutConnectors(crtc)); } - + let info = self.get_plane(plane).map_err(|source| Error::Access { errmsg: "Failed to get plane info", dev: self.dev_path(), - source + source, })?; let filter = info.possible_crtcs(); if !self.resources.filter_crtcs(filter).contains(&crtc) { return Err(Error::PlaneNotCompatible(crtc, plane)); } - + let active = match &*self.internal { DrmDeviceInternal::Atomic(dev) => dev.active.clone(), DrmDeviceInternal::Legacy(dev) => dev.active.clone(), @@ -288,13 +319,29 @@ impl DrmDevice { _ => unreachable!(), }; - DrmSurfaceInternal::Atomic(AtomicDrmSurface::new(self.internal.clone(), active, crtc, plane, mapping, mode, connectors, self.logger.clone())?) + DrmSurfaceInternal::Atomic(AtomicDrmSurface::new( + self.internal.clone(), + active, + crtc, + plane, + mapping, + mode, + connectors, + self.logger.clone(), + )?) } else { if self.plane_type(plane)? != PlaneType::Primary { return Err(Error::NonPrimaryPlane(plane)); } - DrmSurfaceInternal::Legacy(LegacyDrmSurface::new(self.internal.clone(), active, crtc, mode, connectors, self.logger.clone())?) + DrmSurfaceInternal::Legacy(LegacyDrmSurface::new( + self.internal.clone(), + active, + crtc, + mode, + connectors, + self.logger.clone(), + )?) }; // get plane formats @@ -304,18 +351,25 @@ impl DrmDevice { source, })?; let mut formats = HashSet::new(); - for code in plane_info.formats().iter().flat_map(|x| Fourcc::try_from(*x).ok()) { + for code in plane_info + .formats() + .iter() + .flat_map(|x| Fourcc::try_from(*x).ok()) + { formats.insert(Format { code, modifier: Modifier::Invalid, }); } - if let (Ok(1), &DrmSurfaceInternal::Atomic(ref surf)) = (self.get_driver_capability(DriverCapability::AddFB2Modifiers), &internal) { + if let (Ok(1), &DrmSurfaceInternal::Atomic(ref surf)) = ( + self.get_driver_capability(DriverCapability::AddFB2Modifiers), + &internal, + ) { let set = self.get_properties(plane).map_err(|source| Error::Access { errmsg: "Failed to query properties", dev: self.dev_path(), - source + source, })?; if let Ok(prop) = surf.plane_prop_handle(plane, "IN_FORMATS") { let prop_info = self.get_property(prop).map_err(|source| Error::Access { @@ -324,7 +378,11 @@ impl DrmDevice { source, })?; let (handles, raw_values) = set.as_props_and_values(); - let raw_value = raw_values[handles.iter().enumerate().find_map(|(i, handle)| if *handle == prop { Some(i) } else { None }).unwrap()]; + let raw_value = raw_values[handles + .iter() + .enumerate() + .find_map(|(i, handle)| if *handle == prop { Some(i) } else { None }) + .unwrap()]; if let property::Value::Blob(blob) = prop_info.value_type().convert_value(raw_value) { let data = self.get_property_blob(blob).map_err(|source| Error::Access { errmsg: "Failed to query property blob data", @@ -337,8 +395,14 @@ impl DrmDevice { let fmt_mod_blob_ptr = data.as_ptr() as *const drm_ffi::drm_format_modifier_blob; let fmt_mod_blob = &*fmt_mod_blob_ptr; - let formats_ptr: *const u32 = fmt_mod_blob_ptr.cast::().offset(fmt_mod_blob.formats_offset as isize) as *const _; - let modifiers_ptr: *const drm_ffi::drm_format_modifier = fmt_mod_blob_ptr.cast::().offset(fmt_mod_blob.modifiers_offset as isize) as *const _; + let formats_ptr: *const u32 = fmt_mod_blob_ptr + .cast::() + .offset(fmt_mod_blob.formats_offset as isize) + as *const _; + let modifiers_ptr: *const drm_ffi::drm_format_modifier = fmt_mod_blob_ptr + .cast::() + .offset(fmt_mod_blob.modifiers_offset as isize) + as *const _; let formats_ptr = formats_ptr as *const u32; let modifiers_ptr = modifiers_ptr as *const drm_ffi::drm_format_modifier; @@ -346,13 +410,15 @@ impl DrmDevice { let mod_info = modifiers_ptr.offset(i as isize).read_unaligned(); for j in 0..64 { if mod_info.formats & (1u64 << j) != 0 { - let code = Fourcc::try_from(formats_ptr.offset((j + mod_info.offset) as isize).read_unaligned()).ok(); + let code = Fourcc::try_from( + formats_ptr + .offset((j + mod_info.offset) as isize) + .read_unaligned(), + ) + .ok(); let modifier = Modifier::from(mod_info.modifier); if let Some(code) = code { - formats.insert(Format { - code, - modifier, - }); + formats.insert(Format { code, modifier }); } } } @@ -377,7 +443,10 @@ impl DrmDevice { }); } - info!(self.logger, "Supported scan-out formats for plane ({:?}): {:?}", plane, formats); + info!( + self.logger, + "Supported scan-out formats for plane ({:?}): {:?}", plane, formats + ); Ok(DrmSurface { crtc, diff --git a/src/backend/drm/error.rs b/src/backend/drm/error.rs index 6edee60..1a2587e 100644 --- a/src/backend/drm/error.rs +++ b/src/backend/drm/error.rs @@ -1,7 +1,7 @@ //use crate::backend::graphics::SwapBuffersError; +use crate::backend::SwapBuffersError; use drm::control::{connector, crtc, plane, Mode, RawResourceHandle}; use std::path::PathBuf; -use crate::backend::SwapBuffersError; /// Errors thrown by the [`DrmDevice`](::backend::drm::DrmDevice) /// and the [`DrmSurface`](::backend::drm::DrmSurface). @@ -66,14 +66,15 @@ impl From for SwapBuffersError { x @ Error::DeviceInactive => SwapBuffersError::TemporaryFailure(Box::new(x)), Error::Access { errmsg, dev, source, .. - } if matches!(source, - drm::SystemError::PermissionDenied | - drm::SystemError::Unknown { - errno: nix::errno::Errno::EBUSY, - } | - drm::SystemError::Unknown { - errno: nix::errno::Errno::EINTR, - } + } if matches!( + source, + drm::SystemError::PermissionDenied + | drm::SystemError::Unknown { + errno: nix::errno::Errno::EBUSY, + } + | drm::SystemError::Unknown { + errno: nix::errno::Errno::EINTR, + } ) => { SwapBuffersError::TemporaryFailure(Box::new(Error::Access { errmsg, dev, source })) @@ -81,4 +82,4 @@ impl From for SwapBuffersError { x => SwapBuffersError::ContextLost(Box::new(x)), } } -} \ No newline at end of file +} diff --git a/src/backend/drm/mod.rs b/src/backend/drm/mod.rs index 63d6d7d..26e0957 100644 --- a/src/backend/drm/mod.rs +++ b/src/backend/drm/mod.rs @@ -1,11 +1,11 @@ pub(crate) mod device; -pub(self) mod surface; pub(self) mod error; -pub(self) mod session; mod render; +pub(self) mod session; +pub(self) mod surface; -pub use device::{DrmDevice, DrmSource, DeviceHandler, device_bind, Planes, DevPath}; -pub use surface::DrmSurface; +pub use device::{device_bind, DevPath, DeviceHandler, DrmDevice, DrmSource, Planes}; pub use error::Error as DrmError; +pub use render::{DrmRenderSurface, Error as DrmRenderError}; pub use session::DrmDeviceObserver; -pub use render::{DrmRenderSurface, Error as DrmRenderError}; \ No newline at end of file +pub use surface::DrmSurface; diff --git a/src/backend/drm/render.rs b/src/backend/drm/render.rs index d306d6b..4ace014 100644 --- a/src/backend/drm/render.rs +++ b/src/backend/drm/render.rs @@ -1,20 +1,22 @@ -use std::os::unix::io::AsRawFd; use std::collections::HashSet; use std::convert::TryInto; +use std::os::unix::io::AsRawFd; use std::sync::Arc; use cgmath::Matrix3; use drm::buffer::PlanarBuffer; -use drm::control::{Device, Mode, crtc, connector, framebuffer, plane}; -use gbm::{Device as GbmDevice, BufferObject, BufferObjectFlags}; +use drm::control::{connector, crtc, framebuffer, plane, Device, Mode}; +use gbm::{BufferObject, BufferObjectFlags, Device as GbmDevice}; #[cfg(feature = "wayland_frontend")] -use wayland_server::protocol::{wl_shm, wl_buffer}; +use wayland_server::protocol::{wl_buffer, wl_shm}; -use crate::backend::SwapBuffersError; -use crate::backend::allocator::{Allocator, Format, Fourcc, Modifier, Swapchain, SwapchainError, Slot, Buffer, dmabuf::Dmabuf}; -use crate::backend::renderer::{Renderer, Bind, Transform, Texture}; +use super::{device::DevPath, surface::DrmSurfaceInternal, DrmError, DrmSurface}; +use crate::backend::allocator::{ + dmabuf::Dmabuf, Allocator, Buffer, Format, Fourcc, Modifier, Slot, Swapchain, SwapchainError, +}; use crate::backend::egl::EGLBuffer; -use super::{DrmSurface, DrmError, device::DevPath, surface::DrmSurfaceInternal}; +use crate::backend::renderer::{Bind, Renderer, Texture, Transform}; +use crate::backend::SwapBuffersError; pub struct DrmRenderSurface< D: AsRawFd + 'static, @@ -33,16 +35,20 @@ pub struct DrmRenderSurface< impl DrmRenderSurface where D: AsRawFd + 'static, - A: Allocator, - B: Buffer + TryInto, - R: Bind + Renderer, + A: Allocator, + B: Buffer + TryInto, + R: Bind + Renderer, E1: std::error::Error + 'static, E2: std::error::Error + 'static, E3: std::error::Error + 'static, { #[allow(clippy::type_complexity)] - pub fn new>>(drm: DrmSurface, allocator: A, renderer: R, log: L) -> Result, Error> - { + pub fn new>>( + drm: DrmSurface, + allocator: A, + renderer: R, + log: L, + ) -> Result, Error> { // we cannot simply pick the first supported format of the intersection of *all* formats, because: // - we do not want something like Abgr4444, which looses color information // - some formats might perform terribly @@ -56,14 +62,29 @@ where let logger = crate::slog_or_fallback(log).new(o!("backend" => "drm_render")); // select a format - let plane_formats = drm.supported_formats().iter().filter(|fmt| fmt.code == code).cloned().collect::>(); - let renderer_formats = Bind::::supported_formats(&renderer).expect("Dmabuf renderer without formats") - .iter().filter(|fmt| fmt.code == code).cloned().collect::>(); + let plane_formats = drm + .supported_formats() + .iter() + .filter(|fmt| fmt.code == code) + .cloned() + .collect::>(); + let renderer_formats = Bind::::supported_formats(&renderer) + .expect("Dmabuf renderer without formats") + .iter() + .filter(|fmt| fmt.code == code) + .cloned() + .collect::>(); trace!(logger, "Remaining plane formats: {:?}", plane_formats); trace!(logger, "Remaining renderer formats: {:?}", renderer_formats); - debug!(logger, "Remaining intersected formats: {:?}", plane_formats.intersection(&renderer_formats).collect::>()); - + debug!( + logger, + "Remaining intersected formats: {:?}", + plane_formats + .intersection(&renderer_formats) + .collect::>() + ); + if plane_formats.is_empty() { return Err(Error::NoSupportedPlaneFormat); } else if renderer_formats.is_empty() { @@ -74,38 +95,48 @@ where // Special case: if a format supports explicit LINEAR (but no implicit Modifiers) // and the other doesn't support any modifier, force LINEAR. This will force the allocator to // create a buffer with a LINEAR layout instead of an implicit modifier. - if - (plane_formats.len() == 1 && - plane_formats.iter().next().unwrap().modifier == Modifier::Invalid - && renderer_formats.iter().all(|x| x.modifier != Modifier::Invalid) - && renderer_formats.iter().any(|x| x.modifier == Modifier::Linear) - ) || (renderer_formats.len() == 1 && - renderer_formats.iter().next().unwrap().modifier == Modifier::Invalid + if (plane_formats.len() == 1 + && plane_formats.iter().next().unwrap().modifier == Modifier::Invalid + && renderer_formats.iter().all(|x| x.modifier != Modifier::Invalid) + && renderer_formats.iter().any(|x| x.modifier == Modifier::Linear)) + || (renderer_formats.len() == 1 + && renderer_formats.iter().next().unwrap().modifier == Modifier::Invalid && plane_formats.iter().all(|x| x.modifier != Modifier::Invalid) - && plane_formats.iter().any(|x| x.modifier == Modifier::Linear) - ) { + && plane_formats.iter().any(|x| x.modifier == Modifier::Linear)) + { vec![Format { code, modifier: Modifier::Linear, }] } else { - plane_formats.intersection(&renderer_formats).cloned().collect::>() + plane_formats + .intersection(&renderer_formats) + .cloned() + .collect::>() } }; debug!(logger, "Testing Formats: {:?}", formats); // Test explicit formats first let drm = Arc::new(drm); - let iter = formats.iter().filter(|x| x.modifier != Modifier::Invalid && x.modifier != Modifier::Linear) + let iter = formats + .iter() + .filter(|x| x.modifier != Modifier::Invalid && x.modifier != Modifier::Linear) .chain(formats.iter().find(|x| x.modifier == Modifier::Linear)) - .chain(formats.iter().find(|x| x.modifier == Modifier::Invalid)).cloned(); + .chain(formats.iter().find(|x| x.modifier == Modifier::Invalid)) + .cloned(); DrmRenderSurface::new_internal(drm, allocator, renderer, iter, logger) } #[allow(clippy::type_complexity)] - fn new_internal(drm: Arc>, allocator: A, mut renderer: R, mut formats: impl Iterator, logger: ::slog::Logger) -> Result, Error> - { + fn new_internal( + drm: Arc>, + allocator: A, + mut renderer: R, + mut formats: impl Iterator, + logger: ::slog::Logger, + ) -> Result, Error> { let format = formats.next().ok_or(Error::NoSupportedPlaneFormat)?; let mode = drm.pending_mode(); @@ -117,16 +148,28 @@ where { let dmabuf: Dmabuf = (*buffer).clone(); - match renderer.bind(dmabuf).map_err(Error::::RenderError) - .and_then(|_| renderer.begin(mode.size().0 as u32, mode.size().1 as u32, Transform::Normal).map_err(Error::RenderError)) - .and_then(|_| renderer.clear([0.0, 0.0, 0.0, 1.0]).map_err(Error::RenderError)) - .and_then(|_| renderer.finish().map_err(|_| Error::InitialRenderingError)) - .and_then(|_| renderer.unbind().map_err(Error::RenderError)) + match renderer + .bind(dmabuf) + .map_err(Error::::RenderError) + .and_then(|_| { + renderer + .begin(mode.size().0 as u32, mode.size().1 as u32, Transform::Normal) + .map_err(Error::RenderError) + }) + .and_then(|_| renderer.clear([0.0, 0.0, 0.0, 1.0]).map_err(Error::RenderError)) + .and_then(|_| renderer.finish().map_err(|_| Error::InitialRenderingError)) + .and_then(|_| renderer.unbind().map_err(Error::RenderError)) { - Ok(_) => {}, + Ok(_) => {} Err(err) => { warn!(logger, "Rendering failed with format {:?}: {}", format, err); - return DrmRenderSurface::new_internal(drm, swapchain.allocator, renderer, formats, logger); + return DrmRenderSurface::new_internal( + drm, + swapchain.allocator, + renderer, + formats, + logger, + ); } } } @@ -135,8 +178,7 @@ where let fb = bo.userdata().unwrap().unwrap().fb; buffer.set_userdata(bo); - match drm.test_buffer(fb, &mode, true) - { + match drm.test_buffer(fb, &mode, true) { Ok(_) => { debug!(logger, "Success, choosen format: {:?}", format); let buffers = Buffers::new(drm.clone(), gbm, buffer); @@ -148,18 +190,21 @@ where buffers, current_buffer: None, }) - }, + } Err(err) => { - warn!(logger, "Mode-setting failed with buffer format {:?}: {}", format, err); + warn!( + logger, + "Mode-setting failed with buffer format {:?}: {}", format, err + ); DrmRenderSurface::new_internal(drm, swapchain.allocator, renderer, formats, logger) } } } - + pub fn queue_frame(&mut self) -> Result<(), Error> { let mode = self.drm.pending_mode(); let (width, height) = (mode.size().0 as u32, mode.size().1 as u32); - self.begin(width, height, Transform::Flipped180/* TODO */) + self.begin(width, height, Transform::Flipped180 /* TODO */) } pub fn drop_frame(&mut self) -> Result<(), SwapBuffersError> { @@ -177,11 +222,11 @@ where pub fn frame_submitted(&mut self) -> Result<(), Error> { self.buffers.submitted() } - + pub fn crtc(&self) -> crtc::Handle { self.drm.crtc() } - + pub fn plane(&self) -> plane::Handle { self.drm.plane() } @@ -219,13 +264,12 @@ where } } - impl Renderer for DrmRenderSurface where D: AsRawFd + 'static, - A: Allocator, - B: Buffer + TryInto, - R: Bind + Renderer, + A: Allocator, + B: Buffer + TryInto, + R: Bind + Renderer, T: Texture, E1: std::error::Error + 'static, E2: std::error::Error + 'static, @@ -235,7 +279,10 @@ where type TextureId = T; #[cfg(feature = "image")] - fn import_bitmap>(&mut self, image: &image::ImageBuffer, C>) -> Result { + fn import_bitmap>( + &mut self, + image: &image::ImageBuffer, C>, + ) -> Result { self.renderer.import_bitmap(image).map_err(Error::RenderError) } @@ -248,16 +295,16 @@ where fn import_shm(&mut self, buffer: &wl_buffer::WlBuffer) -> Result { self.renderer.import_shm(buffer).map_err(Error::RenderError) } - + #[cfg(feature = "wayland_frontend")] fn import_egl(&mut self, buffer: &EGLBuffer) -> Result { - self.renderer.import_egl(buffer).map_err(Error::RenderError) + self.renderer.import_egl(buffer).map_err(Error::RenderError) } fn destroy_texture(&mut self, texture: Self::TextureId) -> Result<(), Self::Error> { self.renderer.destroy_texture(texture).map_err(Error::RenderError) } - + fn begin(&mut self, width: u32, height: u32, transform: Transform) -> Result<(), Error> { if self.current_buffer.is_some() { return Ok(()); @@ -266,15 +313,24 @@ where let slot = self.swapchain.acquire()?.ok_or(Error::NoFreeSlotsError)?; self.renderer.bind((*slot).clone()).map_err(Error::RenderError)?; self.current_buffer = Some(slot); - self.renderer.begin(width, height, transform).map_err(Error::RenderError) + self.renderer + .begin(width, height, transform) + .map_err(Error::RenderError) } - fn clear(&mut self, color: [f32; 4]) -> Result<(), Self::Error> { + fn clear(&mut self, color: [f32; 4]) -> Result<(), Self::Error> { self.renderer.clear(color).map_err(Error::RenderError) } - - fn render_texture(&mut self, texture: &Self::TextureId, matrix: Matrix3, alpha: f32) -> Result<(), Self::Error> { - self.renderer.render_texture(texture, matrix, alpha).map_err(Error::RenderError) + + fn render_texture( + &mut self, + texture: &Self::TextureId, + matrix: Matrix3, + alpha: f32, + ) -> Result<(), Self::Error> { + self.renderer + .render_texture(texture, matrix, alpha) + .map_err(Error::RenderError) } fn finish(&mut self) -> Result<(), SwapBuffersError> { @@ -284,7 +340,10 @@ where let result = self.renderer.finish(); if result.is_ok() { - match self.buffers.queue::(self.current_buffer.take().unwrap()) { + match self + .buffers + .queue::(self.current_buffer.take().unwrap()) + { Ok(()) => {} Err(Error::DrmError(drm)) => return Err(drm.into()), Err(Error::GbmError(err)) => return Err(SwapBuffersError::ContextLost(Box::new(err))), @@ -318,7 +377,11 @@ impl Buffers where D: AsRawFd + 'static, { - pub fn new(drm: Arc>, gbm: GbmDevice, slot: Slot>>) -> Buffers { + pub fn new( + drm: Arc>, + gbm: GbmDevice, + slot: Slot>>, + ) -> Buffers { Buffers { drm, gbm, @@ -328,7 +391,10 @@ where } } - pub fn queue(&mut self, slot: Slot>>) -> Result<(), Error> + pub fn queue( + &mut self, + slot: Slot>>, + ) -> Result<(), Error> where E1: std::error::Error + 'static, E2: std::error::Error + 'static, @@ -347,7 +413,7 @@ where } } - pub fn submitted(&mut self) -> Result<(), Error> + pub fn submitted(&mut self) -> Result<(), Error> where E1: std::error::Error + 'static, E2: std::error::Error + 'static, @@ -364,7 +430,7 @@ where } } - fn submit(&mut self) -> Result<(), Error> + fn submit(&mut self) -> Result<(), Error> where E1: std::error::Error + 'static, E2: std::error::Error + 'static, @@ -386,7 +452,11 @@ where } } -fn import_dmabuf(drm: &Arc>, gbm: &GbmDevice, buffer: &Dmabuf) -> Result>, Error> +fn import_dmabuf( + drm: &Arc>, + gbm: &GbmDevice, + buffer: &Dmabuf, +) -> Result>, Error> where A: AsRawFd + 'static, E1: std::error::Error + 'static, @@ -399,32 +469,29 @@ where Modifier::Invalid => None, x => Some(x), }; - + let logger = match &*(*drm).internal { DrmSurfaceInternal::Atomic(surf) => surf.logger.clone(), DrmSurfaceInternal::Legacy(surf) => surf.logger.clone(), }; - let fb = match - if modifier.is_some() { - let num = bo.plane_count().unwrap(); - let modifiers = [ - modifier, - if num > 1 { modifier } else { None }, - if num > 2 { modifier } else { None }, - if num > 3 { modifier } else { None }, - ]; - drm.add_planar_framebuffer(&bo, &modifiers, drm_ffi::DRM_MODE_FB_MODIFIERS) - } else { - drm.add_planar_framebuffer(&bo, &[None, None, None, None], 0) - } - { + let fb = match if modifier.is_some() { + let num = bo.plane_count().unwrap(); + let modifiers = [ + modifier, + if num > 1 { modifier } else { None }, + if num > 2 { modifier } else { None }, + if num > 3 { modifier } else { None }, + ]; + drm.add_planar_framebuffer(&bo, &modifiers, drm_ffi::DRM_MODE_FB_MODIFIERS) + } else { + drm.add_planar_framebuffer(&bo, &[None, None, None, None], 0) + } { Ok(fb) => fb, Err(source) => { // We only support this as a fallback of last resort for ARGB8888 visuals, // like xf86-video-modesetting does. - if drm::buffer::Buffer::format(&bo) != Fourcc::Argb8888 - || bo.handles()[1].is_some() { + if drm::buffer::Buffer::format(&bo) != Fourcc::Argb8888 || bo.handles()[1].is_some() { return Err(Error::DrmError(DrmError::Access { errmsg: "Failed to add framebuffer", dev: drm.dev_path(), @@ -432,17 +499,15 @@ where })); } debug!(logger, "Failed to add framebuffer, trying legacy method"); - drm.add_framebuffer(&bo, 32, 32).map_err(|source| DrmError::Access { - errmsg: "Failed to add framebuffer", - dev: drm.dev_path(), - source, - })? + drm.add_framebuffer(&bo, 32, 32) + .map_err(|source| DrmError::Access { + errmsg: "Failed to add framebuffer", + dev: drm.dev_path(), + source, + })? } }; - bo.set_userdata(FbHandle { - drm: drm.clone(), - fb, - }).unwrap(); + bo.set_userdata(FbHandle { drm: drm.clone(), fb }).unwrap(); Ok(bo) } @@ -471,21 +536,21 @@ where #[error("The swapchain encounted an error: {0}")] SwapchainError(#[from] SwapchainError), #[error("The renderer encounted an error: {0}")] - RenderError(#[source] E3) + RenderError(#[source] E3), } impl< - E1: std::error::Error + 'static, - E2: std::error::Error + 'static, - E3: std::error::Error + Into + 'static, -> From> for SwapBuffersError { + E1: std::error::Error + 'static, + E2: std::error::Error + 'static, + E3: std::error::Error + Into + 'static, + > From> for SwapBuffersError +{ fn from(err: Error) -> SwapBuffersError { match err { x @ Error::NoSupportedPlaneFormat | x @ Error::NoSupportedRendererFormat | x @ Error::FormatsNotCompatible - | x @ Error::InitialRenderingError - => SwapBuffersError::ContextLost(Box::new(x)), + | x @ Error::InitialRenderingError => SwapBuffersError::ContextLost(Box::new(x)), x @ Error::NoFreeSlotsError => SwapBuffersError::TemporaryFailure(Box::new(x)), Error::DrmError(err) => err.into(), Error::GbmError(err) => SwapBuffersError::ContextLost(Box::new(err)), @@ -493,4 +558,4 @@ impl< Error::RenderError(err) => err.into(), } } -} \ No newline at end of file +} diff --git a/src/backend/drm/session.rs b/src/backend/drm/session.rs index a03e844..6529cf1 100644 --- a/src/backend/drm/session.rs +++ b/src/backend/drm/session.rs @@ -1,5 +1,8 @@ -use std::sync::{Arc, Weak, atomic::{AtomicBool, Ordering}}; use std::os::unix::io::{AsRawFd, RawFd}; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Weak, +}; use drm::Device as BasicDevice; use nix::libc::dev_t; @@ -92,17 +95,17 @@ impl DrmDeviceObserver { } } } - + // okay, the previous session/whatever might left the drm devices in any state... // lets fix that if let Err(err) = self.reset_state() { warn!(self.logger, "Unable to reset state after tty switch: {}", err); // TODO call drm-handler::error } - + self.active.store(true, Ordering::SeqCst); } - + fn reset_state(&mut self) -> Result<(), Error> { if let Some(dev) = self.dev.upgrade() { dev.reset_state() @@ -110,4 +113,4 @@ impl DrmDeviceObserver { Ok(()) } } -} \ No newline at end of file +} diff --git a/src/backend/drm/surface/atomic.rs b/src/backend/drm/surface/atomic.rs index 0de3a72..1ba4f57 100644 --- a/src/backend/drm/surface/atomic.rs +++ b/src/backend/drm/surface/atomic.rs @@ -6,11 +6,14 @@ use drm::control::{ use std::collections::HashSet; use std::os::unix::io::AsRawFd; -use std::sync::{atomic::{AtomicBool, Ordering}, Arc, Mutex, RwLock}; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Mutex, RwLock, +}; use crate::backend::drm::{ - device::{DevPath, DrmDeviceInternal}, device::atomic::Mapping, + device::{DevPath, DrmDeviceInternal}, error::Error, }; @@ -48,7 +51,11 @@ impl AtomicDrmSurface { let logger = logger.new(o!("smithay_module" => "backend_drm_atomic", "drm_module" => "surface")); info!( logger, - "Initializing drm surface ({:?}:{:?}) with mode {:?} and connectors {:?}", crtc, plane, mode, connectors + "Initializing drm surface ({:?}:{:?}) with mode {:?} and connectors {:?}", + crtc, + plane, + mode, + connectors ); let crtc_info = fd.get_crtc(crtc).map_err(|source| Error::Access { @@ -63,30 +70,25 @@ impl AtomicDrmSurface { // 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) => fd - .create_property_blob(&mode) - .map_err(|source| Error::Access { - errmsg: "Failed to create Property Blob for mode", - dev: fd.dev_path(), - source, - })?, - None => property::Value::Unknown(0), - }; - - let blob = fd - .create_property_blob(&mode) - .map_err(|source| Error::Access { + Some(mode) => fd.create_property_blob(&mode).map_err(|source| Error::Access { errmsg: "Failed to create Property Blob for mode", dev: fd.dev_path(), source, - })?; + })?, + None => property::Value::Unknown(0), + }; - let res_handles = fd.resource_handles() - .map_err(|source| Error::Access { - errmsg: "Error loading drm resources", - dev: fd.dev_path(), - source, - })?; + let blob = fd.create_property_blob(&mode).map_err(|source| Error::Access { + errmsg: "Failed to create Property Blob for mode", + dev: fd.dev_path(), + source, + })?; + + let res_handles = fd.resource_handles().map_err(|source| Error::Access { + errmsg: "Error loading drm resources", + dev: fd.dev_path(), + source, + })?; // the current set of connectors are those, that already have the correct `CRTC_ID` set. // so we collect them for `current_state` and set the user-given once in `pending_state`. @@ -94,8 +96,7 @@ impl AtomicDrmSurface { // If they don't match, `commit_pending` will return true and they will be changed on the next `commit`. let mut current_connectors = HashSet::new(); for conn in res_handles.connectors() { - let crtc_prop = - prop_mapping + let crtc_prop = prop_mapping .0 .get(&conn) .expect("Unknown handle") @@ -105,8 +106,7 @@ impl AtomicDrmSurface { name: "CRTC_ID", }) .map(|x| *x)?; - if let (Ok(crtc_prop_info), Ok(props)) = (fd.get_property(crtc_prop), fd.get_properties(*conn)) - { + if let (Ok(crtc_prop_info), Ok(props)) = (fd.get_property(crtc_prop), fd.get_properties(*conn)) { let (ids, vals) = props.as_props_and_values(); for (&id, &val) in ids.iter().zip(vals.iter()) { if id == crtc_prop { @@ -152,14 +152,20 @@ impl AtomicDrmSurface { // here we create a dumbbuffer for that purpose. fn create_test_buffer(&self, mode: &Mode) -> Result { let (w, h) = mode.size(); - let db = self.fd - .create_dumb_buffer((w as u32, h as u32), crate::backend::allocator::Fourcc::Argb8888, 32) + let db = self + .fd + .create_dumb_buffer( + (w as u32, h as u32), + crate::backend::allocator::Fourcc::Argb8888, + 32, + ) .map_err(|source| Error::Access { errmsg: "Failed to create dumb buffer", dev: self.fd.dev_path(), source, })?; - let fb = self.fd + let fb = self + .fd .add_framebuffer(&db, 32, 32) .map_err(|source| Error::Access { errmsg: "Failed to create framebuffer", @@ -198,13 +204,11 @@ impl AtomicDrmSurface { return Err(Error::DeviceInactive); } - let info = self.fd - .get_connector(conn) - .map_err(|source| Error::Access { - errmsg: "Error loading connector info", - dev: self.fd.dev_path(), - source, - })?; + let info = self.fd.get_connector(conn).map_err(|source| Error::Access { + errmsg: "Error loading connector info", + dev: self.fd.dev_path(), + source, + })?; let mut pending = self.pending.write().unwrap(); @@ -219,11 +223,12 @@ impl AtomicDrmSurface { Some(pending.mode), Some(pending.blob), )?; - self.fd.atomic_commit( - &[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly], - req, - ) - .map_err(|_| Error::TestFailed(self.crtc))?; + self.fd + .atomic_commit( + &[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly], + req, + ) + .map_err(|_| Error::TestFailed(self.crtc))?; // seems to be, lets add the connector pending.connectors.insert(conn); @@ -255,11 +260,12 @@ impl AtomicDrmSurface { Some(pending.mode), Some(pending.blob), )?; - self.fd.atomic_commit( - &[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly], - req, - ) - .map_err(|_| Error::TestFailed(self.crtc))?; + self.fd + .atomic_commit( + &[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly], + req, + ) + .map_err(|_| Error::TestFailed(self.crtc))?; // seems to be, lets remove the connector pending.connectors.remove(&conn); @@ -293,11 +299,12 @@ impl AtomicDrmSurface { Some(pending.blob), )?; - self.fd.atomic_commit( - &[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly], - req, - ) - .map_err(|_| Error::TestFailed(self.crtc))?; + self.fd + .atomic_commit( + &[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly], + req, + ) + .map_err(|_| Error::TestFailed(self.crtc))?; pending.connectors = conns; @@ -312,7 +319,8 @@ impl AtomicDrmSurface { let mut pending = self.pending.write().unwrap(); // check if new config is supported - let new_blob = self.fd + let new_blob = self + .fd .create_property_blob(&mode) .map_err(|source| Error::Access { errmsg: "Failed to create Property Blob for mode", @@ -329,7 +337,8 @@ impl AtomicDrmSurface { Some(mode), Some(new_blob), )?; - if let Err(err) = self.fd + if let Err(err) = self + .fd .atomic_commit( &[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly], req, @@ -346,7 +355,7 @@ impl AtomicDrmSurface { Ok(()) } - + pub fn commit_pending(&self) -> bool { *self.pending.read().unwrap() != *self.state.read().unwrap() } @@ -403,7 +412,8 @@ impl AtomicDrmSurface { Some(pending.blob), )?; - if let Err(err) = self.fd + if let Err(err) = self + .fd .atomic_commit( &[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly], req.clone(), @@ -429,7 +439,8 @@ impl AtomicDrmSurface { }; debug!(self.logger, "Setting screen: {:?}", req); - let result = self.fd + let result = self + .fd .atomic_commit( if event { &[ @@ -441,10 +452,7 @@ impl AtomicDrmSurface { AtomicCommitFlags::Nonblock, ] } else { - &[ - AtomicCommitFlags::AllowModeset, - AtomicCommitFlags::Nonblock, - ] + &[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::Nonblock] }, req, ) @@ -480,36 +488,38 @@ impl AtomicDrmSurface { // If we would set anything here, that would require a modeset, this would fail, // indicating a problem in our assumptions. trace!(self.logger, "Queueing page flip: {:?}", req); - self.fd.atomic_commit( - if event { - &[AtomicCommitFlags::PageFlipEvent, AtomicCommitFlags::Nonblock] - } else { - &[AtomicCommitFlags::Nonblock] - }, - req, - ) - .map_err(|source| Error::Access { - errmsg: "Page flip commit failed", - dev: self.fd.dev_path(), - source, - })?; + self.fd + .atomic_commit( + if event { + &[AtomicCommitFlags::PageFlipEvent, AtomicCommitFlags::Nonblock] + } else { + &[AtomicCommitFlags::Nonblock] + }, + req, + ) + .map_err(|source| Error::Access { + errmsg: "Page flip commit failed", + dev: self.fd.dev_path(), + source, + })?; Ok(()) } - + pub fn test_buffer(&self, fb: framebuffer::Handle, mode: &Mode) -> Result { if !self.active.load(Ordering::SeqCst) { return Err(Error::DeviceInactive); } - let blob = self.fd + let blob = self + .fd .create_property_blob(&mode) .map_err(|source| Error::Access { errmsg: "Failed to create Property Blob for mode", dev: self.fd.dev_path(), source, })?; - + let current = self.state.read().unwrap(); let pending = self.pending.read().unwrap(); @@ -524,10 +534,16 @@ impl AtomicDrmSurface { self.plane, Some(fb), Some(*mode), - Some(blob) + Some(blob), )?; - let result = self.fd.atomic_commit(&[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly], req).is_ok(); + let result = self + .fd + .atomic_commit( + &[AtomicCommitFlags::AllowModeset, AtomicCommitFlags::TestOnly], + req, + ) + .is_ok(); Ok(result) } @@ -536,8 +552,7 @@ impl AtomicDrmSurface { handle: connector::Handle, name: &'static str, ) -> Result { - self - .prop_mapping + self.prop_mapping .0 .get(&handle) .expect("Unknown handle") @@ -549,9 +564,12 @@ impl AtomicDrmSurface { .map(|x| *x) } - pub(crate) fn crtc_prop_handle(&self, handle: crtc::Handle, name: &'static str) -> Result { - self - .prop_mapping + pub(crate) fn crtc_prop_handle( + &self, + handle: crtc::Handle, + name: &'static str, + ) -> Result { + self.prop_mapping .1 .get(&handle) .expect("Unknown handle") @@ -569,8 +587,7 @@ impl AtomicDrmSurface { handle: framebuffer::Handle, name: &'static str, ) -> Result { - self - .prop_mapping + self.prop_mapping .2 .get(&handle) .expect("Unknown handle") @@ -587,8 +604,7 @@ impl AtomicDrmSurface { handle: plane::Handle, name: &'static str, ) -> Result { - self - .prop_mapping + self.prop_mapping .3 .get(&handle) .expect("Unknown handle") @@ -657,7 +673,7 @@ impl AtomicDrmSurface { property::Value::Framebuffer(Some(fb)), ); } - + // we also need to connect the plane req.add_property( plane, @@ -733,10 +749,12 @@ impl AtomicDrmSurface { property::Value::Framebuffer(None), ); - self.fd.atomic_commit(&[AtomicCommitFlags::TestOnly], req.clone()) + self.fd + .atomic_commit(&[AtomicCommitFlags::TestOnly], req.clone()) .map_err(|_| Error::TestFailed(self.crtc))?; - self.fd.atomic_commit(&[AtomicCommitFlags::Nonblock], req) + self.fd + .atomic_commit(&[AtomicCommitFlags::Nonblock], req) .map_err(|source| Error::Access { errmsg: "Failed to commit on clear_plane", dev: self.fd.dev_path(), @@ -763,10 +781,7 @@ impl Drop for AtomicDrmSurface { // other ttys that use no cursor, might not clear it themselves. // This makes sure our cursor won't stay visible. if let Err(err) = self.clear_plane() { - warn!( - self.logger, - "Failed to clear plane on {:?}: {}", self.crtc, err - ); + warn!(self.logger, "Failed to clear plane on {:?}: {}", self.crtc, err); } // disable connectors again diff --git a/src/backend/drm/surface/legacy.rs b/src/backend/drm/surface/legacy.rs index 9a31c5d..11ed92b 100644 --- a/src/backend/drm/surface/legacy.rs +++ b/src/backend/drm/surface/legacy.rs @@ -1,15 +1,15 @@ -use drm::control::{ - connector, crtc, encoder, framebuffer, Device as ControlDevice, Mode, - PageFlipFlags, -}; +use drm::control::{connector, crtc, encoder, framebuffer, Device as ControlDevice, Mode, PageFlipFlags}; use std::collections::HashSet; use std::os::unix::io::AsRawFd; -use std::sync::{atomic::{AtomicBool, Ordering}, Arc, RwLock}; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, RwLock, +}; use crate::backend::drm::{ - device::{DevPath, DrmDeviceInternal}, device::legacy::set_connector_state, + device::{DevPath, DrmDeviceInternal}, error::Error, }; @@ -54,12 +54,11 @@ impl LegacyDrmSurface { let current_mode = crtc_info.mode(); let mut current_connectors = HashSet::new(); - let res_handles = fd.resource_handles() - .map_err(|source| Error::Access { - errmsg: "Error loading drm resources", - dev: fd.dev_path(), - source, - })?; + let res_handles = fd.resource_handles().map_err(|source| Error::Access { + errmsg: "Error loading drm resources", + dev: fd.dev_path(), + source, + })?; for &con in res_handles.connectors() { let con_info = fd.get_connector(con).map_err(|source| Error::Access { errmsg: "Error loading connector info", @@ -179,7 +178,8 @@ impl LegacyDrmSurface { // check the connectors to see if this mode is supported for connector in &pending.connectors { - if !self.fd + if !self + .fd .get_connector(*connector) .map_err(|source| Error::Access { errmsg: "Error loading connector info", @@ -229,7 +229,8 @@ impl LegacyDrmSurface { if conn_removed { // null commit (necessary to trigger removal on the kernel side with the legacy api.) - self.fd.set_crtc(self.crtc, None, (0, 0), &[], None) + self.fd + .set_crtc(self.crtc, None, (0, 0), &[], None) .map_err(|source| Error::Access { errmsg: "Error setting crtc", dev: self.fd.dev_path(), @@ -253,22 +254,23 @@ impl LegacyDrmSurface { debug!(self.logger, "Setting screen"); // do a modeset and attach the given framebuffer - self.fd.set_crtc( - self.crtc, - Some(framebuffer), - (0, 0), - &pending - .connectors - .iter() - .copied() - .collect::>(), - Some(pending.mode), - ) - .map_err(|source| Error::Access { - errmsg: "Error setting crtc", - dev: self.fd.dev_path(), - source, - })?; + self.fd + .set_crtc( + self.crtc, + Some(framebuffer), + (0, 0), + &pending + .connectors + .iter() + .copied() + .collect::>(), + Some(pending.mode), + ) + .map_err(|source| Error::Access { + errmsg: "Error setting crtc", + dev: self.fd.dev_path(), + source, + })?; *current = pending.clone(); @@ -306,7 +308,11 @@ impl LegacyDrmSurface { &*self.fd, self.crtc, framebuffer, - if event { &[PageFlipFlags::PageFlipEvent] } else { &[] }, + if event { + &[PageFlipFlags::PageFlipEvent] + } else { + &[] + }, None, ) .map_err(|source| Error::Access { @@ -320,21 +326,24 @@ impl LegacyDrmSurface { if !self.active.load(Ordering::SeqCst) { return Err(Error::DeviceInactive); } - + let pending = self.pending.read().unwrap(); - + debug!(self.logger, "Setting screen for buffer *testing*"); - Ok(self.fd.set_crtc( - self.crtc, - Some(fb), - (0, 0), - &pending - .connectors - .iter() - .copied() - .collect::>(), - Some(*mode), - ).is_ok()) + Ok(self + .fd + .set_crtc( + self.crtc, + Some(fb), + (0, 0), + &pending + .connectors + .iter() + .copied() + .collect::>(), + Some(*mode), + ) + .is_ok()) } // we use this function to verify, if a certain connector/mode combination @@ -345,13 +354,11 @@ impl LegacyDrmSurface { // Better would be some kind of test commit to ask the driver, // but that only exists for the atomic api. fn check_connector(&self, conn: connector::Handle, mode: &Mode) -> Result { - let info = self.fd - .get_connector(conn) - .map_err(|source| Error::Access { - errmsg: "Error loading connector info", - dev: self.fd.dev_path(), - source, - })?; + let info = self.fd.get_connector(conn).map_err(|source| Error::Access { + errmsg: "Error loading connector info", + dev: self.fd.dev_path(), + source, + })?; // check if the connector can handle the current mode if info.modes().contains(mode) { @@ -362,12 +369,11 @@ impl LegacyDrmSurface { .filter(|enc| enc.is_some()) .map(|enc| enc.unwrap()) .map(|encoder| { - self.fd.get_encoder(encoder) - .map_err(|source| Error::Access { - errmsg: "Error loading encoder info", - dev: self.fd.dev_path(), - source, - }) + self.fd.get_encoder(encoder).map_err(|source| Error::Access { + errmsg: "Error loading encoder info", + dev: self.fd.dev_path(), + source, + }) }) .collect::, _>>()?; @@ -406,9 +412,7 @@ impl Drop for LegacyDrmSurface { // disable connectors again let current = self.state.read().unwrap(); - if set_connector_state(&*self.fd, current.connectors.iter().copied(), false) - .is_ok() - { + if set_connector_state(&*self.fd, current.connectors.iter().copied(), false).is_ok() { // null commit let _ = self.fd.set_crtc(self.crtc, None, (0, 0), &[], None); } diff --git a/src/backend/drm/surface/mod.rs b/src/backend/drm/surface/mod.rs index 1fd5d61..5550a40 100644 --- a/src/backend/drm/surface/mod.rs +++ b/src/backend/drm/surface/mod.rs @@ -2,18 +2,17 @@ use std::collections::HashSet; use std::os::unix::io::{AsRawFd, RawFd}; use std::sync::Arc; +use drm::control::{connector, crtc, framebuffer, plane, Device as ControlDevice, Mode}; use drm::Device as BasicDevice; -use drm::control::{Device as ControlDevice, Mode, crtc, connector, framebuffer, plane}; pub(super) mod atomic; pub(super) mod legacy; use super::error::Error; +use crate::backend::allocator::Format; use atomic::AtomicDrmSurface; use legacy::LegacyDrmSurface; -use crate::backend::allocator::Format; -pub struct DrmSurface -{ +pub struct DrmSurface { pub(super) crtc: crtc::Handle, pub(super) plane: plane::Handle, pub(super) internal: Arc>, @@ -46,7 +45,7 @@ impl DrmSurface { pub fn plane(&self) -> plane::Handle { self.plane } - + /// Currently used [`connector`](drm::control::connector)s of this `Surface` pub fn current_connectors(&self) -> impl IntoIterator { match &*self.internal { @@ -185,12 +184,21 @@ impl DrmSurface { &self.formats } - pub fn test_buffer(&self, fb: framebuffer::Handle, mode: &Mode, allow_screen_change: bool) -> Result { + pub fn test_buffer( + &self, + fb: framebuffer::Handle, + mode: &Mode, + allow_screen_change: bool, + ) -> Result { match &*self.internal { DrmSurfaceInternal::Atomic(surf) => surf.test_buffer(fb, mode), - DrmSurfaceInternal::Legacy(surf) => if allow_screen_change { - surf.test_buffer(fb, mode) - } else { Ok(false) } // There is no test-commiting with the legacy interface + DrmSurfaceInternal::Legacy(surf) => { + if allow_screen_change { + surf.test_buffer(fb, mode) + } else { + Ok(false) + } + } // There is no test-commiting with the legacy interface } } -} \ No newline at end of file +} diff --git a/src/backend/egl/context.rs b/src/backend/egl/context.rs index 752de85..518e415 100644 --- a/src/backend/egl/context.rs +++ b/src/backend/egl/context.rs @@ -6,7 +6,6 @@ use super::{ffi, wrap_egl_call, Error, MakeCurrentError}; use crate::backend::egl::display::{EGLDisplay, PixelFormat}; use crate::backend::egl::EGLSurface; - /// EGL context for rendering #[derive(Debug)] pub struct EGLContext { @@ -20,10 +19,7 @@ unsafe impl Send for EGLContext {} unsafe impl Sync for EGLContext {} impl EGLContext { - pub fn new( - display: &EGLDisplay, - log: L, - ) -> Result + pub fn new(display: &EGLDisplay, log: L) -> Result where L: Into>, { @@ -43,17 +39,13 @@ impl EGLContext { Self::new_internal(display, None, Some((attributes, reqs)), log) } - pub fn new_shared( - display: &EGLDisplay, - share: &EGLContext, - log: L, - ) -> Result + pub fn new_shared(display: &EGLDisplay, share: &EGLContext, log: L) -> Result where L: Into>, { Self::new_internal(display, Some(share), None, log) } - + pub fn new_shared_with_config( display: &EGLDisplay, share: &EGLContext, @@ -82,13 +74,26 @@ impl EGLContext { Some((attributes, reqs)) => { let (format, config_id) = display.choose_config(attributes, reqs)?; (Some(format), config_id) - }, + } None => { - if !display.extensions.iter().any(|x| x == "EGL_KHR_no_config_context") && - !display.extensions.iter().any(|x| x == "EGL_MESA_configless_context") && - !display.extensions.iter().any(|x| x == "EGL_KHR_surfaceless_context") + if !display + .extensions + .iter() + .any(|x| x == "EGL_KHR_no_config_context") + && !display + .extensions + .iter() + .any(|x| x == "EGL_MESA_configless_context") + && !display + .extensions + .iter() + .any(|x| x == "EGL_KHR_surfaceless_context") { - return Err(Error::EglExtensionNotSupported(&["EGL_KHR_no_config_context", "EGL_MESA_configless_context", "EGL_KHR_surfaceless_context"])); + return Err(Error::EglExtensionNotSupported(&[ + "EGL_KHR_no_config_context", + "EGL_MESA_configless_context", + "EGL_KHR_surfaceless_context", + ])); } (None, ffi::egl::NO_CONFIG_KHR) } @@ -99,7 +104,9 @@ impl EGLContext { if let Some((attributes, _)) = config { let version = attributes.version; - if display.egl_version >= (1, 5) || display.extensions.iter().any(|s| s == "EGL_KHR_create_context") { + if display.egl_version >= (1, 5) + || display.extensions.iter().any(|s| s == "EGL_KHR_create_context") + { trace!(log, "Setting CONTEXT_MAJOR_VERSION to {}", version.0); context_attributes.push(ffi::egl::CONTEXT_MAJOR_VERSION as i32); context_attributes.push(version.0 as i32); @@ -134,7 +141,9 @@ impl EGLContext { ffi::egl::CreateContext( **display.display, config_id, - shared.map(|context| context.context).unwrap_or(ffi::egl::NO_CONTEXT), + shared + .map(|context| context.context) + .unwrap_or(ffi::egl::NO_CONTEXT), context_attributes.as_ptr(), ) }) @@ -157,12 +166,13 @@ impl EGLContext { /// /// This function is marked unsafe, because the context cannot be made current /// on multiple threads. - pub unsafe fn make_current_with_surface(&self, surface: &EGLSurface) -> Result<(), MakeCurrentError> - { + pub unsafe fn make_current_with_surface(&self, surface: &EGLSurface) -> Result<(), MakeCurrentError> { let surface_ptr = surface.surface.load(Ordering::SeqCst); - wrap_egl_call(|| ffi::egl::MakeCurrent(**self.display.display, surface_ptr, surface_ptr, self.context)) - .map(|_| ()) - .map_err(Into::into) + wrap_egl_call(|| { + ffi::egl::MakeCurrent(**self.display.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. diff --git a/src/backend/egl/display.rs b/src/backend/egl/display.rs index b268f70..54b2940 100644 --- a/src/backend/egl/display.rs +++ b/src/backend/egl/display.rs @@ -1,10 +1,10 @@ //! Type safe native types for safe egl initialisation use std::collections::HashSet; -use std::sync::Arc; use std::ffi::CStr; use std::mem::MaybeUninit; use std::ops::Deref; +use std::sync::Arc; use nix::libc::c_int; #[cfg(all(feature = "use_system_lib", feature = "wayland_frontend"))] @@ -12,13 +12,13 @@ use wayland_server::{protocol::wl_buffer::WlBuffer, Display}; #[cfg(feature = "use_system_lib")] use wayland_sys::server::wl_display; -use crate::backend::allocator::{Buffer, dmabuf::Dmabuf, Fourcc, Modifier, Format as DrmFormat}; +use crate::backend::allocator::{dmabuf::Dmabuf, Buffer, Format as DrmFormat, Fourcc, Modifier}; use crate::backend::egl::{ - ffi::egl::types::EGLImage, - ffi, wrap_egl_call, EGLError, Error, context::{GlAttributes, PixelFormatRequirements}, - native::{EGLNativeDisplay}, - BufferAccessError, EGLBuffer, Format, + ffi, + ffi::egl::types::EGLImage, + native::EGLNativeDisplay, + wrap_egl_call, BufferAccessError, EGLBuffer, EGLError, Error, Format, }; /// Wrapper around [`ffi::EGLDisplay`](ffi::egl::types::EGLDisplay) to ensure display is only destroyed @@ -94,7 +94,7 @@ impl EGLDisplay { return Err(Error::EglExtensionNotSupported(native.required_extensions())); } } - + let (platform, native_ptr, attributes) = native.platform_display(); // we create an EGLDisplay let display = unsafe { @@ -355,62 +355,92 @@ impl EGLDisplay { /// Imports a dmabuf as an eglimage pub fn create_image_from_dmabuf(&self, dmabuf: &Dmabuf) -> Result { - if !self.extensions.iter().any(|s| s == "EGL_KHR_image_base") && - !self.extensions.iter().any(|s| s == "EGL_EXT_image_dma_buf_import") + if !self.extensions.iter().any(|s| s == "EGL_KHR_image_base") + && !self + .extensions + .iter() + .any(|s| s == "EGL_EXT_image_dma_buf_import") { - return Err(Error::EglExtensionNotSupported(&["EGL_KHR_image_base", "EGL_EXT_image_dma_buf_import"])); + return Err(Error::EglExtensionNotSupported(&[ + "EGL_KHR_image_base", + "EGL_EXT_image_dma_buf_import", + ])); } - if dmabuf.has_modifier() && !self.extensions.iter().any(|s| s == "EGL_EXT_image_dma_buf_import_modifiers") { - return Err(Error::EglExtensionNotSupported(&["EGL_EXT_image_dma_buf_import_modifiers"])); + if dmabuf.has_modifier() + && !self + .extensions + .iter() + .any(|s| s == "EGL_EXT_image_dma_buf_import_modifiers") + { + return Err(Error::EglExtensionNotSupported(&[ + "EGL_EXT_image_dma_buf_import_modifiers", + ])); }; let mut out: Vec = Vec::with_capacity(50); out.extend(&[ - ffi::egl::WIDTH as i32, dmabuf.width() as i32, - ffi::egl::HEIGHT as i32, dmabuf.height() as i32, - ffi::egl::LINUX_DRM_FOURCC_EXT as i32, dmabuf.format().code as u32 as i32, + ffi::egl::WIDTH as i32, + dmabuf.width() as i32, + ffi::egl::HEIGHT as i32, + dmabuf.height() as i32, + ffi::egl::LINUX_DRM_FOURCC_EXT as i32, + dmabuf.format().code as u32 as i32, ]); - + let names = [ [ ffi::egl::DMA_BUF_PLANE0_FD_EXT, ffi::egl::DMA_BUF_PLANE0_OFFSET_EXT, ffi::egl::DMA_BUF_PLANE0_PITCH_EXT, ffi::egl::DMA_BUF_PLANE0_MODIFIER_LO_EXT, - ffi::egl::DMA_BUF_PLANE0_MODIFIER_HI_EXT - ], [ + ffi::egl::DMA_BUF_PLANE0_MODIFIER_HI_EXT, + ], + [ ffi::egl::DMA_BUF_PLANE1_FD_EXT, ffi::egl::DMA_BUF_PLANE1_OFFSET_EXT, ffi::egl::DMA_BUF_PLANE1_PITCH_EXT, ffi::egl::DMA_BUF_PLANE1_MODIFIER_LO_EXT, - ffi::egl::DMA_BUF_PLANE1_MODIFIER_HI_EXT - ], [ + ffi::egl::DMA_BUF_PLANE1_MODIFIER_HI_EXT, + ], + [ ffi::egl::DMA_BUF_PLANE2_FD_EXT, ffi::egl::DMA_BUF_PLANE2_OFFSET_EXT, ffi::egl::DMA_BUF_PLANE2_PITCH_EXT, ffi::egl::DMA_BUF_PLANE2_MODIFIER_LO_EXT, - ffi::egl::DMA_BUF_PLANE2_MODIFIER_HI_EXT - ], [ + ffi::egl::DMA_BUF_PLANE2_MODIFIER_HI_EXT, + ], + [ ffi::egl::DMA_BUF_PLANE3_FD_EXT, ffi::egl::DMA_BUF_PLANE3_OFFSET_EXT, ffi::egl::DMA_BUF_PLANE3_PITCH_EXT, ffi::egl::DMA_BUF_PLANE3_MODIFIER_LO_EXT, - ffi::egl::DMA_BUF_PLANE3_MODIFIER_HI_EXT - ] + ffi::egl::DMA_BUF_PLANE3_MODIFIER_HI_EXT, + ], ]; - for (i, ((fd, offset), stride)) in dmabuf.handles().iter().zip(dmabuf.offsets()).zip(dmabuf.strides()).enumerate() { + for (i, ((fd, offset), stride)) in dmabuf + .handles() + .iter() + .zip(dmabuf.offsets()) + .zip(dmabuf.strides()) + .enumerate() + { out.extend(&[ - names[i][0] as i32, *fd, - names[i][1] as i32, *offset as i32, - names[i][2] as i32, *stride as i32, + names[i][0] as i32, + *fd, + names[i][1] as i32, + *offset as i32, + names[i][2] as i32, + *stride as i32, ]); if dmabuf.has_modifier() { out.extend(&[ - names[i][3] as i32, (Into::::into(dmabuf.format().modifier) & 0xFFFFFFFF) as i32, - names[i][4] as i32, (Into::::into(dmabuf.format().modifier) >> 32) as i32, + names[i][3] as i32, + (Into::::into(dmabuf.format().modifier) & 0xFFFFFFFF) as i32, + names[i][4] as i32, + (Into::::into(dmabuf.format().modifier) >> 32) as i32, ]) } } @@ -460,8 +490,11 @@ impl EGLDisplay { } } -fn get_dmabuf_formats(display: &ffi::egl::types::EGLDisplay, extensions: &[String], log: &::slog::Logger) -> Result<(HashSet, HashSet), EGLError> -{ +fn get_dmabuf_formats( + display: &ffi::egl::types::EGLDisplay, + extensions: &[String], + log: &::slog::Logger, +) -> Result<(HashSet, HashSet), EGLError> { use std::convert::TryFrom; if !extensions.iter().any(|s| s == "EGL_EXT_image_dma_buf_import") { @@ -475,11 +508,11 @@ fn get_dmabuf_formats(display: &ffi::egl::types::EGLDisplay, extensions: &[Strin // supported; it's the intended way to just try to create buffers. // Just a guess but better than not supporting dmabufs at all, // given that the modifiers extension isn't supported everywhere. - if !extensions.iter().any(|s| s == "EGL_EXT_image_dma_buf_import_modifiers") { - vec![ - Fourcc::Argb8888, - Fourcc::Xrgb8888, - ] + if !extensions + .iter() + .any(|s| s == "EGL_EXT_image_dma_buf_import_modifiers") + { + vec![Fourcc::Argb8888, Fourcc::Xrgb8888] } else { let mut num = 0i32; wrap_egl_call(|| unsafe { @@ -490,12 +523,20 @@ fn get_dmabuf_formats(display: &ffi::egl::types::EGLDisplay, extensions: &[Strin } let mut formats: Vec = Vec::with_capacity(num as usize); wrap_egl_call(|| unsafe { - ffi::egl::QueryDmaBufFormatsEXT(*display, num, formats.as_mut_ptr() as *mut _, &mut num as *mut _) + ffi::egl::QueryDmaBufFormatsEXT( + *display, + num, + formats.as_mut_ptr() as *mut _, + &mut num as *mut _, + ) })?; unsafe { formats.set_len(num as usize); } - formats.into_iter().flat_map(|x| Fourcc::try_from(x).ok()).collect::>() + formats + .into_iter() + .flat_map(|x| Fourcc::try_from(x).ok()) + .collect::>() } }; @@ -505,24 +546,38 @@ fn get_dmabuf_formats(display: &ffi::egl::types::EGLDisplay, extensions: &[Strin for fourcc in formats { let mut num = 0i32; wrap_egl_call(|| unsafe { - ffi::egl::QueryDmaBufModifiersEXT(*display, fourcc as i32, 0, std::ptr::null_mut(), std::ptr::null_mut(), &mut num as *mut _) + ffi::egl::QueryDmaBufModifiersEXT( + *display, + fourcc as i32, + 0, + std::ptr::null_mut(), + std::ptr::null_mut(), + &mut num as *mut _, + ) })?; if num == 0 { texture_formats.insert(DrmFormat { code: fourcc, - modifier: Modifier::Invalid + modifier: Modifier::Invalid, }); render_formats.insert(DrmFormat { code: fourcc, - modifier: Modifier::Invalid + modifier: Modifier::Invalid, }); } else { let mut mods: Vec = Vec::with_capacity(num as usize); let mut external: Vec = Vec::with_capacity(num as usize); wrap_egl_call(|| unsafe { - ffi::egl::QueryDmaBufModifiersEXT(*display, fourcc as i32, num, mods.as_mut_ptr(), external.as_mut_ptr(), &mut num as *mut _) + ffi::egl::QueryDmaBufModifiersEXT( + *display, + fourcc as i32, + num, + mods.as_mut_ptr(), + external.as_mut_ptr(), + &mut num as *mut _, + ) })?; unsafe { @@ -572,10 +627,7 @@ impl fmt::Debug for EGLBufferReader { #[cfg(feature = "use_system_lib")] impl EGLBufferReader { fn new(display: Arc, wayland: *mut wl_display) -> Self { - Self { - display, - wayland, - } + Self { display, wayland } } /// Try to receive [`EGLImages`] from a given [`WlBuffer`]. @@ -605,9 +657,15 @@ impl EGLBufferReader { x if x == ffi::egl::TEXTURE_RGB as i32 => Format::RGB, x if x == ffi::egl::TEXTURE_RGBA as i32 => Format::RGBA, ffi::egl::TEXTURE_EXTERNAL_WL => Format::External, - ffi::egl::TEXTURE_Y_UV_WL => return Err(BufferAccessError::UnsupportedMultiPlanarFormat(Format::Y_UV)), - ffi::egl::TEXTURE_Y_U_V_WL => return Err(BufferAccessError::UnsupportedMultiPlanarFormat(Format::Y_U_V)), - ffi::egl::TEXTURE_Y_XUXV_WL => return Err(BufferAccessError::UnsupportedMultiPlanarFormat(Format::Y_XUXV)), + ffi::egl::TEXTURE_Y_UV_WL => { + return Err(BufferAccessError::UnsupportedMultiPlanarFormat(Format::Y_UV)) + } + ffi::egl::TEXTURE_Y_U_V_WL => { + return Err(BufferAccessError::UnsupportedMultiPlanarFormat(Format::Y_U_V)) + } + ffi::egl::TEXTURE_Y_XUXV_WL => { + return Err(BufferAccessError::UnsupportedMultiPlanarFormat(Format::Y_XUXV)) + } x => panic!("EGL returned invalid texture type: {}", x), }; @@ -646,11 +704,7 @@ impl EGLBufferReader { let mut images = Vec::with_capacity(format.num_planes()); for i in 0..format.num_planes() { - let out = [ - ffi::egl::WAYLAND_PLANE_WL as i32, - i as i32, - ffi::egl::NONE as i32, - ]; + let out = [ffi::egl::WAYLAND_PLANE_WL as i32, i as i32, ffi::egl::NONE as i32]; images.push({ wrap_egl_call(|| unsafe { @@ -740,4 +794,4 @@ pub struct PixelFormat { pub multisampling: Option, /// is srgb enabled pub srgb: bool, -} \ No newline at end of file +} diff --git a/src/backend/egl/mod.rs b/src/backend/egl/mod.rs index 47362a4..caf44ee 100644 --- a/src/backend/egl/mod.rs +++ b/src/backend/egl/mod.rs @@ -106,8 +106,11 @@ impl fmt::Debug for BufferAccessError { write!(formatter, "BufferAccessError::EGLImageCreationFailed") } BufferAccessError::EglExtensionNotSupported(ref err) => write!(formatter, "{:?}", err), - BufferAccessError::UnsupportedMultiPlanarFormat(ref fmt) => - write!(formatter, "BufferAccessError::UnsupportedMultiPlanerFormat({:?})", fmt), + BufferAccessError::UnsupportedMultiPlanarFormat(ref fmt) => write!( + formatter, + "BufferAccessError::UnsupportedMultiPlanerFormat({:?})", + fmt + ), } } } @@ -132,9 +135,7 @@ impl std::convert::From for GraphicsSwapBuffersError { } // the rest is either never happening or are unrecoverable x @ SwapBuffersError::EGLSwapBuffers(_) => GraphicsSwapBuffersError::ContextLost(Box::new(x)), - x @ SwapBuffersError::EGLCreateSurface(_) => { - GraphicsSwapBuffersError::ContextLost(Box::new(x)) - } + x @ SwapBuffersError::EGLCreateSurface(_) => GraphicsSwapBuffersError::ContextLost(Box::new(x)), } } } diff --git a/src/backend/egl/native.rs b/src/backend/egl/native.rs index 2d829b0..01b59ca 100644 --- a/src/backend/egl/native.rs +++ b/src/backend/egl/native.rs @@ -1,12 +1,10 @@ //! Type safe native types for safe context/surface creation -use super::{ - display::EGLDisplayHandle, ffi, wrap_egl_call, SwapBuffersError, -}; +use super::{display::EGLDisplayHandle, ffi, wrap_egl_call, SwapBuffersError}; use nix::libc::{c_int, c_void}; -use std::sync::Arc; #[cfg(feature = "backend_gbm")] use std::os::unix::io::AsRawFd; +use std::sync::Arc; #[cfg(feature = "backend_winit")] use wayland_egl as wegl; @@ -33,7 +31,11 @@ impl EGLNativeDisplay for GbmDevice { &["EGL_MESA_platform_gbm"] } fn platform_display(&self) -> (ffi::egl::types::EGLenum, *mut c_void, Vec) { - (ffi::egl::PLATFORM_GBM_MESA, self.as_raw() as *mut _, vec![ffi::egl::NONE as ffi::EGLint]) + ( + ffi::egl::PLATFORM_GBM_MESA, + self.as_raw() as *mut _, + vec![ffi::egl::NONE as ffi::EGLint], + ) } } @@ -51,9 +53,17 @@ impl EGLNativeDisplay for WinitWindow { fn platform_display(&self) -> (ffi::egl::types::EGLenum, *mut c_void, Vec) { if let Some(display) = self.wayland_display() { - (ffi::egl::PLATFORM_WAYLAND_EXT, display as *mut _, vec![ffi::egl::NONE as ffi::EGLint]) + ( + ffi::egl::PLATFORM_WAYLAND_EXT, + display as *mut _, + vec![ffi::egl::NONE as ffi::EGLint], + ) } else if let Some(display) = self.xlib_display() { - (ffi::egl::PLATFORM_X11_EXT, display as *mut _, vec![ffi::egl::NONE as ffi::EGLint]) + ( + ffi::egl::PLATFORM_X11_EXT, + display as *mut _, + vec![ffi::egl::NONE as ffi::EGLint], + ) } else { unreachable!("No backends for winit other then Wayland and X11 are supported") } @@ -91,13 +101,13 @@ pub unsafe trait EGLNativeSurface: Send + Sync { } /// If the surface supports resizing you may implement and use this function. - /// + /// /// The two first arguments (width, height) are the new size of the surface, /// the two others (dx, dy) represent the displacement of the top-left corner of the surface. /// It allows you to control the direction of the resizing if necessary. - /// + /// /// Implementations may ignore the dx and dy arguments. - /// + /// /// Returns true if the resize was successful. fn resize(&self, _width: i32, _height: i32, _dx: i32, _dy: i32) -> bool { false @@ -160,7 +170,7 @@ unsafe impl EGLNativeSurface for wegl::WlEglSurface { ) }) } - + fn resize(&self, width: i32, height: i32, dx: i32, dy: i32) -> bool { wegl::WlEglSurface::resize(self, width, height, dx, dy); true diff --git a/src/backend/egl/surface.rs b/src/backend/egl/surface.rs index 0d3e863..ef610c0 100644 --- a/src/backend/egl/surface.rs +++ b/src/backend/egl/surface.rs @@ -9,11 +9,11 @@ use nix::libc::c_int; use crate::backend::egl::{ display::{EGLDisplay, EGLDisplayHandle, PixelFormat}, + ffi, native::EGLNativeSurface, - ffi, EGLError, SwapBuffersError + EGLError, SwapBuffersError, }; - /// EGL surface of a given EGL context for rendering pub struct EGLSurface { pub(crate) display: Arc, @@ -98,14 +98,17 @@ impl EGLSurface { ); if self.native.needs_recreation() || surface.is_null() || is_bad_surface { - let previous = self.surface.compare_exchange( - surface, - self.native - .create(&self.display, self.config_id, &self.surface_attributes) - .map_err(SwapBuffersError::EGLCreateSurface)? as *mut _, - Ordering::SeqCst, - Ordering::SeqCst, - ).expect("The surface pointer changed in between?"); + let previous = self + .surface + .compare_exchange( + surface, + self.native + .create(&self.display, self.config_id, &self.surface_attributes) + .map_err(SwapBuffersError::EGLCreateSurface)? as *mut _, + Ordering::SeqCst, + Ordering::SeqCst, + ) + .expect("The surface pointer changed in between?"); if previous == surface && !surface.is_null() { let _ = unsafe { ffi::egl::DestroySurface(**self.display, surface as *const _) }; } @@ -139,15 +142,15 @@ impl EGLSurface { pub fn pixel_format(&self) -> PixelFormat { self.pixel_format } - + /// Tries to resize the underlying native surface. - /// + /// /// The two first arguments (width, height) are the new size of the surface, /// the two others (dx, dy) represent the displacement of the top-left corner of the surface. /// It allows you to control the direction of the resizing if necessary. - /// + /// /// Implementations may ignore the dx and dy arguments. - /// + /// /// Returns true if the resize was successful. pub fn resize(&self, width: i32, height: i32, dx: i32, dy: i32) -> bool { self.native.resize(width, height, dx, dy) diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 577ce07..ae565b8 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -18,8 +18,8 @@ #![allow(missing_docs)] //pub mod graphics; -pub mod input; pub mod allocator; +pub mod input; pub mod renderer; #[cfg(feature = "backend_drm")] @@ -66,4 +66,4 @@ pub enum SwapBuffersError { /// recreation. #[error("A temporary condition caused the page flip to fail: {0}")] TemporaryFailure(Box), -} \ No newline at end of file +} diff --git a/src/backend/renderer/gles2/mod.rs b/src/backend/renderer/gles2/mod.rs index 7330069..306ea9a 100644 --- a/src/backend/renderer/gles2/mod.rs +++ b/src/backend/renderer/gles2/mod.rs @@ -6,13 +6,18 @@ use std::rc::Rc; use cgmath::{prelude::*, Matrix3}; mod shaders; +use super::{Bind, Renderer, Texture, Transform, Unbind}; +use crate::backend::allocator::{ + dmabuf::{Dmabuf, WeakDmabuf}, + Format, +}; +use crate::backend::egl::{ + ffi::egl::types::EGLImage, EGLBuffer, EGLContext, EGLSurface, Format as EGLFormat, MakeCurrentError, +}; use crate::backend::SwapBuffersError; -use crate::backend::allocator::{dmabuf::{Dmabuf, WeakDmabuf}, Format}; -use crate::backend::egl::{EGLContext, EGLSurface, EGLBuffer, Format as EGLFormat, ffi::egl::types::EGLImage, MakeCurrentError}; -use super::{Renderer, Bind, Unbind, Transform, Texture}; #[cfg(feature = "wayland_frontend")] -use wayland_server::protocol::{wl_shm, wl_buffer}; +use wayland_server::protocol::{wl_buffer, wl_shm}; #[allow(clippy::all, missing_docs)] pub mod ffi { @@ -109,44 +114,52 @@ impl From for SwapBuffersError { | x @ Gles2Error::ProgramLinkError | x @ Gles2Error::GLFunctionLoaderError | x @ Gles2Error::GLExtensionNotSupported(_) - | x @ Gles2Error::UnconstraintRenderingOperation - => SwapBuffersError::ContextLost(Box::new(x)), + | x @ Gles2Error::UnconstraintRenderingOperation => SwapBuffersError::ContextLost(Box::new(x)), Gles2Error::ContextActivationError(err) => err.into(), x @ Gles2Error::FramebufferBindingError | x @ Gles2Error::BindBufferEGLError(_) | x @ Gles2Error::UnsupportedPixelFormat(_) - | x @ Gles2Error::BufferAccessError(_) - => SwapBuffersError::TemporaryFailure(Box::new(x)), + | x @ Gles2Error::BufferAccessError(_) => SwapBuffersError::TemporaryFailure(Box::new(x)), } } } -extern "system" fn gl_debug_log(_source: ffi::types::GLenum, - gltype: ffi::types::GLenum, - _id: ffi::types::GLuint, - _severity: ffi::types::GLenum, - _length: ffi::types::GLsizei, - message: *const ffi::types::GLchar, - user_param: *mut nix::libc::c_void) -{ - let _ = std::panic::catch_unwind(move || { - unsafe { - let msg = CStr::from_ptr(message); - let log = Box::from_raw(user_param as *mut ::slog::Logger); - let message_utf8 = msg.to_string_lossy(); - match gltype { - ffi::DEBUG_TYPE_ERROR | ffi::DEBUG_TYPE_UNDEFINED_BEHAVIOR => error!(log, "[GL] {}", message_utf8), - ffi::DEBUG_TYPE_DEPRECATED_BEHAVIOR => warn!(log, "[GL] {}", message_utf8), - _ => debug!(log, "[GL] {}", message_utf8), - }; - std::mem::forget(log); - } +extern "system" fn gl_debug_log( + _source: ffi::types::GLenum, + gltype: ffi::types::GLenum, + _id: ffi::types::GLuint, + _severity: ffi::types::GLenum, + _length: ffi::types::GLsizei, + message: *const ffi::types::GLchar, + user_param: *mut nix::libc::c_void, +) { + let _ = std::panic::catch_unwind(move || unsafe { + let msg = CStr::from_ptr(message); + let log = Box::from_raw(user_param as *mut ::slog::Logger); + let message_utf8 = msg.to_string_lossy(); + match gltype { + ffi::DEBUG_TYPE_ERROR | ffi::DEBUG_TYPE_UNDEFINED_BEHAVIOR => { + error!(log, "[GL] {}", message_utf8) + } + ffi::DEBUG_TYPE_DEPRECATED_BEHAVIOR => warn!(log, "[GL] {}", message_utf8), + _ => debug!(log, "[GL] {}", message_utf8), + }; + std::mem::forget(log); }); } -unsafe fn compile_shader(gl: &ffi::Gles2, variant: ffi::types::GLuint, src: &'static str) -> Result { +unsafe fn compile_shader( + gl: &ffi::Gles2, + variant: ffi::types::GLuint, + src: &'static str, +) -> Result { let shader = gl.CreateShader(variant); - gl.ShaderSource(shader, 1, &src.as_ptr() as *const *const u8 as *const *const i8, &(src.len() as i32) as *const _); + gl.ShaderSource( + shader, + 1, + &src.as_ptr() as *const *const u8 as *const *const i8, + &(src.len() as i32) as *const _, + ); gl.CompileShader(shader); let mut status = ffi::FALSE as i32; @@ -159,7 +172,11 @@ unsafe fn compile_shader(gl: &ffi::Gles2, variant: ffi::types::GLuint, src: &'st Ok(shader) } -unsafe fn link_program(gl: &ffi::Gles2, vert_src: &'static str, frag_src: &'static str) -> Result { +unsafe fn link_program( + gl: &ffi::Gles2, + vert_src: &'static str, + frag_src: &'static str, +) -> Result { let vert = compile_shader(gl, ffi::VERTEX_SHADER, vert_src)?; let frag = compile_shader(gl, ffi::FRAGMENT_SHADER, frag_src)?; let program = gl.CreateProgram(); @@ -183,7 +200,7 @@ unsafe fn link_program(gl: &ffi::Gles2, vert_src: &'static str, frag_src: &'stat unsafe fn texture_program(gl: &ffi::Gles2, frag: &'static str) -> Result { let program = link_program(&gl, shaders::VERTEX_SHADER, frag)?; - + let position = CStr::from_bytes_with_nul(b"position\0").expect("NULL terminated"); let tex_coords = CStr::from_bytes_with_nul(b"tex_coords\0").expect("NULL terminated"); let tex = CStr::from_bytes_with_nul(b"tex\0").expect("NULL terminated"); @@ -205,7 +222,7 @@ unsafe fn texture_program(gl: &ffi::Gles2, frag: &'static str) -> Result(context: EGLContext, logger: L) -> Result where - L: Into> + L: Into>, { let log = crate::slog_or_fallback(logger).new(o!("smithay_module" => "renderer_gles2")); @@ -225,14 +242,28 @@ impl Gles2Renderer { }; info!(log, "Initializing OpenGL ES Renderer"); - info!(log, "GL Version: {:?}", CStr::from_ptr(gl.GetString(ffi::VERSION) as *const i8)); - info!(log, "GL Vendor: {:?}", CStr::from_ptr(gl.GetString(ffi::VENDOR) as *const i8)); - info!(log, "GL Renderer: {:?}", CStr::from_ptr(gl.GetString(ffi::RENDERER) as *const i8)); + info!( + log, + "GL Version: {:?}", + CStr::from_ptr(gl.GetString(ffi::VERSION) as *const i8) + ); + info!( + log, + "GL Vendor: {:?}", + CStr::from_ptr(gl.GetString(ffi::VENDOR) as *const i8) + ); + info!( + log, + "GL Renderer: {:?}", + CStr::from_ptr(gl.GetString(ffi::RENDERER) as *const i8) + ); info!(log, "Supported GL Extensions: {:?}", exts); // required for the manditory wl_shm formats if !exts.iter().any(|ext| ext == "GL_EXT_texture_format_BGRA8888") { - return Err(Gles2Error::GLExtensionNotSupported(&["GL_EXT_texture_format_BGRA8888"])); + return Err(Gles2Error::GLExtensionNotSupported(&[ + "GL_EXT_texture_format_BGRA8888", + ])); } // required for buffers without linear memory layout if !exts.iter().any(|ext| ext == "GL_EXT_unpack_subimage") { @@ -245,17 +276,19 @@ impl Gles2Renderer { gl.Enable(ffi::DEBUG_OUTPUT_SYNCHRONOUS); gl.DebugMessageCallback(Some(gl_debug_log), logger as *mut nix::libc::c_void); Some(logger) - } else { None }; + } else { + None + }; (gl, exts, logger) }; let programs = [ - texture_program(&gl, shaders::FRAGMENT_SHADER_ABGR)?, - texture_program(&gl, shaders::FRAGMENT_SHADER_XBGR)?, - texture_program(&gl, shaders::FRAGMENT_SHADER_BGRA)?, - texture_program(&gl, shaders::FRAGMENT_SHADER_BGRX)?, - texture_program(&gl, shaders::FRAGMENT_SHADER_EXTERNAL)?, + texture_program(&gl, shaders::FRAGMENT_SHADER_ABGR)?, + texture_program(&gl, shaders::FRAGMENT_SHADER_XBGR)?, + texture_program(&gl, shaders::FRAGMENT_SHADER_BGRA)?, + texture_program(&gl, shaders::FRAGMENT_SHADER_BGRX)?, + texture_program(&gl, shaders::FRAGMENT_SHADER_EXTERNAL)?, ]; let renderer = Gles2Renderer { @@ -312,31 +345,45 @@ impl Bind for Gles2Renderer { } } - let buffer = self.buffers + let buffer = self + .buffers .iter() .find(|buffer| dmabuf == buffer.dmabuf) .map(|buf| { - let dmabuf = buf.dmabuf.upgrade().expect("Dmabuf equal check succeeded for freed buffer"); + let dmabuf = buf + .dmabuf + .upgrade() + .expect("Dmabuf equal check succeeded for freed buffer"); Ok(Gles2Buffer { internal: buf.clone(), // we keep the dmabuf alive as long as we are bound - _dmabuf: dmabuf + _dmabuf: dmabuf, }) }) .unwrap_or_else(|| { - let image = self.egl.display.create_image_from_dmabuf(&dmabuf).map_err(Gles2Error::BindBufferEGLError)?; + let image = self + .egl + .display + .create_image_from_dmabuf(&dmabuf) + .map_err(Gles2Error::BindBufferEGLError)?; unsafe { let mut rbo = 0; self.gl.GenRenderbuffers(1, &mut rbo as *mut _); self.gl.BindRenderbuffer(ffi::RENDERBUFFER, rbo); - self.gl.EGLImageTargetRenderbufferStorageOES(ffi::RENDERBUFFER, image); + self.gl + .EGLImageTargetRenderbufferStorageOES(ffi::RENDERBUFFER, image); self.gl.BindRenderbuffer(ffi::RENDERBUFFER, 0); let mut fbo = 0; self.gl.GenFramebuffers(1, &mut fbo as *mut _); self.gl.BindFramebuffer(ffi::FRAMEBUFFER, fbo); - self.gl.FramebufferRenderbuffer(ffi::FRAMEBUFFER, ffi::COLOR_ATTACHMENT0, ffi::RENDERBUFFER, rbo); + self.gl.FramebufferRenderbuffer( + ffi::FRAMEBUFFER, + ffi::COLOR_ATTACHMENT0, + ffi::RENDERBUFFER, + rbo, + ); let status = self.gl.CheckFramebufferStatus(ffi::FRAMEBUFFER); self.gl.BindFramebuffer(ffi::FRAMEBUFFER, 0); @@ -356,7 +403,7 @@ impl Bind for Gles2Renderer { Ok(Gles2Buffer { internal: weak, - _dmabuf: dmabuf + _dmabuf: dmabuf, }) } })?; @@ -364,7 +411,7 @@ impl Bind for Gles2Renderer { unsafe { self.gl.BindFramebuffer(ffi::FRAMEBUFFER, buffer.internal.fbo); } - + self.target_buffer = Some(buffer); Ok(()) } @@ -437,21 +484,36 @@ impl Renderer for Gles2Renderer { wl_shm::Format::Xrgb8888, ] } - + #[cfg(feature = "image")] - fn import_bitmap>(&mut self, image: &image::ImageBuffer, C>) -> Result { + fn import_bitmap>( + &mut self, + image: &image::ImageBuffer, C>, + ) -> Result { self.make_current()?; - + let mut tex = 0; unsafe { self.gl.GenTextures(1, &mut tex); self.gl.BindTexture(ffi::TEXTURE_2D, tex); - self.gl.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_S, ffi::CLAMP_TO_EDGE as i32); - self.gl.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_T, ffi::CLAMP_TO_EDGE as i32); - self.gl.TexImage2D(ffi::TEXTURE_2D, 0, ffi::RGBA as i32, image.width() as i32, image.height() as i32, 0, ffi::RGBA, ffi::UNSIGNED_BYTE as u32, image.as_ptr() as *const _); + self.gl + .TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_S, ffi::CLAMP_TO_EDGE as i32); + self.gl + .TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_T, ffi::CLAMP_TO_EDGE as i32); + self.gl.TexImage2D( + ffi::TEXTURE_2D, + 0, + ffi::RGBA as i32, + image.width() as i32, + image.height() as i32, + 0, + ffi::RGBA, + ffi::UNSIGNED_BYTE as u32, + image.as_ptr() as *const _, + ); self.gl.BindTexture(ffi::TEXTURE_2D, 0); } - + let texture = Gles2Texture { texture: tex, texture_kind: 2, @@ -461,10 +523,9 @@ impl Renderer for Gles2Renderer { height: image.height(), }; self.egl.unbind()?; - + Ok(texture) } - #[cfg(feature = "wayland_frontend")] fn import_shm(&mut self, buffer: &wl_buffer::WlBuffer) -> Result { @@ -472,7 +533,7 @@ impl Renderer for Gles2Renderer { with_buffer_contents(&buffer, |slice, data| { self.make_current()?; - + let offset = data.offset as i32; let width = data.width as i32; let height = data.height as i32; @@ -492,16 +553,28 @@ impl Renderer for Gles2Renderer { wl_shm::Format::Xrgb8888 => (ffi::BGRA_EXT, 3), format => return Err(Gles2Error::UnsupportedPixelFormat(format)), }; - + let mut tex = 0; unsafe { self.gl.GenTextures(1, &mut tex); self.gl.BindTexture(ffi::TEXTURE_2D, tex); - self.gl.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_S, ffi::CLAMP_TO_EDGE as i32); - self.gl.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_T, ffi::CLAMP_TO_EDGE as i32); + self.gl + .TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_S, ffi::CLAMP_TO_EDGE as i32); + self.gl + .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.TexImage2D(ffi::TEXTURE_2D, 0, gl_format as i32, width, height, 0, gl_format, ffi::UNSIGNED_BYTE as u32, slice.as_ptr() as *const _); + self.gl.TexImage2D( + ffi::TEXTURE_2D, + 0, + gl_format as i32, + width, + height, + 0, + gl_format, + ffi::UNSIGNED_BYTE as u32, + slice.as_ptr() as *const _, + ); self.gl.PixelStorei(ffi::UNPACK_ROW_LENGTH, 0); self.gl.BindTexture(ffi::TEXTURE_2D, 0); @@ -516,11 +589,12 @@ impl Renderer for Gles2Renderer { height: height as u32, }; self.egl.unbind()?; - + Ok(texture) - }).map_err(Gles2Error::BufferAccessError)? + }) + .map_err(Gles2Error::BufferAccessError)? } - + #[cfg(feature = "wayland_frontend")] fn import_egl(&mut self, buffer: &EGLBuffer) -> Result { if !self.extensions.iter().any(|ext| ext == "GL_OES_EGL_image") { @@ -530,21 +604,23 @@ impl Renderer for Gles2Renderer { self.make_current()?; let mut tex = 0; - let target = if buffer.format == EGLFormat::External { ffi::TEXTURE_EXTERNAL_OES } else { ffi::TEXTURE_2D }; + let target = if buffer.format == EGLFormat::External { + ffi::TEXTURE_EXTERNAL_OES + } else { + ffi::TEXTURE_2D + }; unsafe { self.gl.GenTextures(1, &mut tex); self.gl.BindTexture(target, tex); - self.gl.EGLImageTargetTexture2DOES( - target, - buffer.image(0).unwrap(), - ); + self.gl + .EGLImageTargetTexture2DOES(target, buffer.image(0).unwrap()); } let texture = Gles2Texture { texture: tex, texture_kind: match buffer.format { - EGLFormat::RGB => 3, + EGLFormat::RGB => 3, EGLFormat::RGBA => 2, EGLFormat::External => 4, _ => unreachable!("EGLBuffer currenly does not expose multi-planar buffers to us"), @@ -555,10 +631,10 @@ impl Renderer for Gles2Renderer { height: buffer.height, }; self.egl.unbind()?; - + Ok(texture) } - + fn destroy_texture(&mut self, texture: Self::TextureId) -> Result<(), Self::Error> { self.make_current()?; @@ -570,12 +646,11 @@ impl Renderer for Gles2Renderer { Ok(()) } - fn begin(&mut self, width: u32, height: u32, transform: Transform) -> Result<(), Gles2Error> { self.make_current()?; unsafe { self.gl.Viewport(0, 0, width as i32, height as i32); - + self.gl.Enable(ffi::BLEND); self.gl.BlendFunc(ffi::ONE, ffi::ONE_MINUS_SRC_ALPHA); } @@ -601,7 +676,7 @@ impl Renderer for Gles2Renderer { self.current_projection = Some(transform.matrix() * renderer); Ok(()) } - + fn clear(&mut self, color: [f32; 4]) -> Result<(), Self::Error> { self.make_current()?; unsafe { @@ -612,7 +687,12 @@ impl Renderer for Gles2Renderer { Ok(()) } - fn render_texture(&mut self, tex: &Self::TextureId, mut matrix: Matrix3, alpha: f32) -> Result<(), Self::Error> { + fn render_texture( + &mut self, + tex: &Self::TextureId, + mut matrix: Matrix3, + alpha: f32, + ) -> Result<(), Self::Error> { self.make_current()?; if self.current_projection.is_none() { return Err(Gles2Error::UnconstraintRenderingOperation); @@ -621,31 +701,63 @@ impl Renderer for Gles2Renderer { //apply output transformation matrix = self.current_projection.as_ref().unwrap() * matrix; - let target = if tex.is_external { ffi::TEXTURE_EXTERNAL_OES } else { ffi::TEXTURE_2D }; + let target = if tex.is_external { + ffi::TEXTURE_EXTERNAL_OES + } else { + ffi::TEXTURE_2D + }; // render unsafe { self.gl.ActiveTexture(ffi::TEXTURE0); self.gl.BindTexture(target, tex.texture); - self.gl.TexParameteri(target, ffi::TEXTURE_MIN_FILTER, ffi::LINEAR as i32); + self.gl + .TexParameteri(target, ffi::TEXTURE_MIN_FILTER, ffi::LINEAR as i32); self.gl.UseProgram(self.programs[tex.texture_kind].program); - + self.gl.Uniform1i(self.programs[tex.texture_kind].uniform_tex, 0); - self.gl.UniformMatrix3fv(self.programs[tex.texture_kind].uniform_matrix, 1, ffi::FALSE, matrix.as_ptr()); - self.gl.Uniform1i(self.programs[tex.texture_kind].uniform_invert_y, if tex.y_inverted { 1 } else { 0 }); - self.gl.Uniform1f(self.programs[tex.texture_kind].uniform_alpha, alpha); - - self.gl.VertexAttribPointer(self.programs[tex.texture_kind].attrib_position as u32, 2, ffi::FLOAT, ffi::FALSE, 0, VERTS.as_ptr() as *const _); - self.gl.VertexAttribPointer(self.programs[tex.texture_kind].attrib_tex_coords as u32, 2, ffi::FLOAT, ffi::FALSE, 0, TEX_COORDS.as_ptr() as *const _); - - self.gl.EnableVertexAttribArray(self.programs[tex.texture_kind].attrib_position as u32); - self.gl.EnableVertexAttribArray(self.programs[tex.texture_kind].attrib_tex_coords as u32); - + self.gl.UniformMatrix3fv( + self.programs[tex.texture_kind].uniform_matrix, + 1, + ffi::FALSE, + matrix.as_ptr(), + ); + self.gl.Uniform1i( + self.programs[tex.texture_kind].uniform_invert_y, + if tex.y_inverted { 1 } else { 0 }, + ); + self.gl + .Uniform1f(self.programs[tex.texture_kind].uniform_alpha, alpha); + + self.gl.VertexAttribPointer( + self.programs[tex.texture_kind].attrib_position as u32, + 2, + ffi::FLOAT, + ffi::FALSE, + 0, + VERTS.as_ptr() as *const _, + ); + self.gl.VertexAttribPointer( + self.programs[tex.texture_kind].attrib_tex_coords as u32, + 2, + ffi::FLOAT, + ffi::FALSE, + 0, + TEX_COORDS.as_ptr() as *const _, + ); + + self.gl + .EnableVertexAttribArray(self.programs[tex.texture_kind].attrib_position as u32); + self.gl + .EnableVertexAttribArray(self.programs[tex.texture_kind].attrib_tex_coords as u32); + self.gl.DrawArrays(ffi::TRIANGLE_STRIP, 0, 4); - - self.gl.DisableVertexAttribArray(self.programs[tex.texture_kind].attrib_position as u32); - self.gl.DisableVertexAttribArray(self.programs[tex.texture_kind].attrib_tex_coords as u32); - + + self.gl + .DisableVertexAttribArray(self.programs[tex.texture_kind].attrib_position as u32); + self.gl + .DisableVertexAttribArray(self.programs[tex.texture_kind].attrib_tex_coords as u32); + self.gl.BindTexture(target, 0); } diff --git a/src/backend/renderer/gles2/shaders.rs b/src/backend/renderer/gles2/shaders.rs index 862e7bc..c23f56c 100644 --- a/src/backend/renderer/gles2/shaders.rs +++ b/src/backend/renderer/gles2/shaders.rs @@ -89,4 +89,4 @@ varying vec2 v_tex_coords; void main() { gl_FragColor = texture2D(tex, v_tex_coords) * alpha; } -"#; \ No newline at end of file +"#; diff --git a/src/backend/renderer/mod.rs b/src/backend/renderer/mod.rs index 0894668..4b1a541 100644 --- a/src/backend/renderer/mod.rs +++ b/src/backend/renderer/mod.rs @@ -3,7 +3,7 @@ use std::error::Error; use cgmath::{prelude::*, Matrix3, Vector2}; #[cfg(feature = "wayland_frontend")] -use wayland_server::protocol::{wl_shm, wl_buffer}; +use wayland_server::protocol::{wl_buffer, wl_shm}; use crate::backend::SwapBuffersError; #[cfg(feature = "renderer_gl")] @@ -26,46 +26,14 @@ pub enum Transform { impl Transform { pub fn matrix(&self) -> Matrix3 { match self { - Transform::Normal => Matrix3::new( - 1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0, - ), - Transform::_90 => Matrix3::new( - 0.0, -1.0, 0.0, - 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, - ), - Transform::_180 => Matrix3::new( - -1.0, 0.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, 0.0, 1.0, - ), - Transform::_270 => Matrix3::new( - 0.0, 1.0, 0.0, - -1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, - ), - Transform::Flipped => Matrix3::new( - -1.0, 0.0, 0.0, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0, - ), - Transform::Flipped90 => Matrix3::new( - 0.0, 1.0, 0.0, - 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, - ), - Transform::Flipped180 => Matrix3::new( - 1.0, 0.0, 0.0, - 0.0, -1.0, 0.0, - 0.0, 0.0, 1.0, - ), - Transform::Flipped270 => Matrix3::new( - 0.0, -1.0, 0.0, - -1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, - ), + Transform::Normal => Matrix3::new(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0), + Transform::_90 => Matrix3::new(0.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0), + Transform::_180 => Matrix3::new(-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0), + Transform::_270 => Matrix3::new(0.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0), + Transform::Flipped => Matrix3::new(-1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0), + Transform::Flipped90 => Matrix3::new(0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0), + Transform::Flipped180 => Matrix3::new(1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0), + Transform::Flipped270 => Matrix3::new(0.0, -1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0), } } @@ -137,7 +105,10 @@ pub trait Renderer { type TextureId: Texture; #[cfg(feature = "image")] - fn import_bitmap>(&mut self, image: &image::ImageBuffer, C>) -> Result; + fn import_bitmap>( + &mut self, + image: &image::ImageBuffer, C>, + ) -> Result; #[cfg(feature = "wayland_frontend")] fn shm_formats(&self) -> &[wl_shm::Format] { // Mandatory @@ -149,14 +120,30 @@ pub trait Renderer { fn import_egl(&mut self, buffer: &EGLBuffer) -> Result; fn destroy_texture(&mut self, texture: Self::TextureId) -> Result<(), Self::Error>; - fn begin(&mut self, width: u32, height: u32, transform: Transform) -> Result<(), ::Error>; + fn begin( + &mut self, + width: u32, + height: u32, + transform: Transform, + ) -> Result<(), ::Error>; fn finish(&mut self) -> Result<(), SwapBuffersError>; - + fn clear(&mut self, color: [f32; 4]) -> Result<(), Self::Error>; - fn render_texture(&mut self, texture: &Self::TextureId, matrix: Matrix3, alpha: f32) -> Result<(), Self::Error>; - fn render_texture_at(&mut self, texture: &Self::TextureId, pos: (i32, i32), transform: Transform, alpha: f32) -> Result<(), Self::Error> { + fn render_texture( + &mut self, + texture: &Self::TextureId, + matrix: Matrix3, + alpha: f32, + ) -> Result<(), Self::Error>; + fn render_texture_at( + &mut self, + texture: &Self::TextureId, + pos: (i32, i32), + transform: Transform, + alpha: f32, + ) -> Result<(), Self::Error> { let mut mat = Matrix3::::identity(); - + // position and scale let size = texture.size(); mat = mat * Matrix3::from_translation(Vector2::new(pos.0 as f32, pos.1 as f32)); @@ -173,5 +160,4 @@ pub trait Renderer { self.render_texture(texture, mat, alpha) } - -} \ No newline at end of file +} diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 66d0b6f..fdebd8d 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -2,28 +2,24 @@ use crate::backend::egl::display::EGLDisplay; use crate::backend::{ - egl::{context::GlAttributes, native, EGLContext, EGLSurface, EGLBuffer, Error as EGLError}, - renderer::{ - Renderer, Bind, Transform, - gles2::{Gles2Renderer, Gles2Error, Gles2Texture}, - }, + egl::{context::GlAttributes, native, EGLBuffer, EGLContext, EGLSurface, Error as EGLError}, input::{ Axis, AxisSource, Event as BackendEvent, InputBackend, InputEvent, KeyState, KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent, TouchMotionEvent, TouchSlot, TouchUpEvent, UnusedEvent, }, -}; -use std::{ - cell::RefCell, - rc::Rc, - time::Instant, + renderer::{ + gles2::{Gles2Error, Gles2Renderer, Gles2Texture}, + Bind, Renderer, Transform, + }, }; use cgmath::Matrix3; +use std::{cell::RefCell, rc::Rc, time::Instant}; use wayland_egl as wegl; -use wayland_server::Display; #[cfg(feature = "wayland_frontend")] -use wayland_server::protocol::{wl_shm, wl_buffer}; +use wayland_server::protocol::{wl_buffer, wl_shm}; +use wayland_server::Display; use winit::{ dpi::{LogicalPosition, LogicalSize, PhysicalSize}, event::{ @@ -37,7 +33,7 @@ use winit::{ }; #[cfg(feature = "use_system_lib")] -use crate::backend::egl::{display::EGLBufferReader}; +use crate::backend::egl::display::EGLBufferReader; /// Errors thrown by the `winit` backends #[derive(thiserror::Error, Debug)] @@ -158,23 +154,33 @@ where let surface = unsafe { wegl::WlEglSurface::new_from_raw(wl_surface as *mut _, size.width as i32, size.height as i32) }; - EGLSurface::new(&display, context.pixel_format().unwrap(), reqs.double_buffer, context.config_id(), surface, log.clone()) - .map_err(EGLError::CreationFailed)? + EGLSurface::new( + &display, + context.pixel_format().unwrap(), + reqs.double_buffer, + context.config_id(), + surface, + log.clone(), + ) + .map_err(EGLError::CreationFailed)? } else if let Some(xlib_window) = winit_window.xlib_window().map(native::XlibWindow) { debug!(log, "Winit backend: X11"); - EGLSurface::new(&display, context.pixel_format().unwrap(), reqs.double_buffer, context.config_id(), xlib_window, log.clone()) - .map_err(EGLError::CreationFailed)? + EGLSurface::new( + &display, + context.pixel_format().unwrap(), + reqs.double_buffer, + context.config_id(), + xlib_window, + log.clone(), + ) + .map_err(EGLError::CreationFailed)? } else { unreachable!("No backends for winit other then Wayland and X11 are supported") }; let _ = context.unbind(); - - ( - display, - context, - surface, - ) + + (display, context, surface) }; let size = Rc::new(RefCell::new(WindowSize { @@ -250,7 +256,7 @@ impl WinitGraphicsBackend { let size = self.size.borrow(); size.physical_size.into() }; - + self.renderer.bind(self.egl.clone())?; self.renderer.begin(width, height, Transform::Normal) } @@ -259,12 +265,15 @@ impl WinitGraphicsBackend { impl Renderer for WinitGraphicsBackend { type Error = Gles2Error; type TextureId = Gles2Texture; - + #[cfg(feature = "image")] - fn import_bitmap>(&mut self, image: &image::ImageBuffer, C>) -> Result { + fn import_bitmap>( + &mut self, + image: &image::ImageBuffer, C>, + ) -> Result { self.renderer.import_bitmap(image) } - + #[cfg(feature = "wayland_frontend")] fn shm_formats(&self) -> &[wl_shm::Format] { Renderer::shm_formats(&self.renderer) @@ -274,17 +283,22 @@ impl Renderer for WinitGraphicsBackend { fn import_shm(&mut self, buffer: &wl_buffer::WlBuffer) -> Result { self.renderer.import_shm(buffer) } - + #[cfg(feature = "wayland_frontend")] fn import_egl(&mut self, buffer: &EGLBuffer) -> Result { - self.renderer.import_egl(buffer) + self.renderer.import_egl(buffer) } fn destroy_texture(&mut self, texture: Self::TextureId) -> Result<(), Self::Error> { self.renderer.destroy_texture(texture) } - fn begin(&mut self, width: u32, height: u32, transform: Transform) -> Result<(), ::Error> { + fn begin( + &mut self, + width: u32, + height: u32, + transform: Transform, + ) -> Result<(), ::Error> { self.renderer.bind(self.egl.clone())?; self.renderer.begin(width, height, transform) } @@ -293,7 +307,12 @@ impl Renderer for WinitGraphicsBackend { self.renderer.clear(color) } - fn render_texture(&mut self, texture: &Self::TextureId, matrix: Matrix3, alpha: f32) -> Result<(), Self::Error> { + fn render_texture( + &mut self, + texture: &Self::TextureId, + matrix: Matrix3, + alpha: f32, + ) -> Result<(), Self::Error> { self.renderer.render_texture(texture, matrix, alpha) } diff --git a/src/wayland/dmabuf/mod.rs b/src/wayland/dmabuf/mod.rs index 63e4798..f734ed6 100644 --- a/src/wayland/dmabuf/mod.rs +++ b/src/wayland/dmabuf/mod.rs @@ -255,7 +255,11 @@ where for f in &*formats { dmabuf.format(f.format as u32); if version >= 3 { - dmabuf.modifier(f.format as u32, (Into::::into(f.modifier) >> 32) as u32, Into::::into(f.modifier) as u32); + dmabuf.modifier( + f.format as u32, + (Into::::into(f.modifier) >> 32) as u32, + Into::::into(f.modifier) as u32, + ); } } },