Merge pull request #426 from i509VCB/x11/multi-window

This commit is contained in:
Victoria Brekenfeld 2021-12-03 20:05:32 +01:00 committed by GitHub
commit 1088e62a6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 617 additions and 419 deletions

View File

@ -30,6 +30,7 @@
- `Present` was merged into the `X11Surface` - `Present` was merged into the `X11Surface`
- `X11Surface::buffer` now additionally returns the age of the buffer - `X11Surface::buffer` now additionally returns the age of the buffer
- `X11Surface` now has an explicit `submit` function - `X11Surface` now has an explicit `submit` function
- `X11Surface` is now multi-window capable.
### Additions ### Additions

View File

@ -1,4 +1,9 @@
use std::{cell::RefCell, rc::Rc, sync::atomic::Ordering, time::Duration}; use std::{
cell::RefCell,
rc::Rc,
sync::{atomic::Ordering, Arc, Mutex},
time::Duration,
};
use slog::Logger; use slog::Logger;
#[cfg(feature = "egl")] #[cfg(feature = "egl")]
@ -7,7 +12,7 @@ use smithay::{
backend::{ backend::{
egl::{EGLContext, EGLDisplay}, egl::{EGLContext, EGLDisplay},
renderer::{gles2::Gles2Renderer, Bind, ImportEgl, Renderer, Transform, Unbind}, renderer::{gles2::Gles2Renderer, Bind, ImportEgl, Renderer, Transform, Unbind},
x11::{X11Backend, X11Event, X11Surface}, x11::{WindowBuilder, X11Backend, X11Event, X11Surface},
SwapBuffersError, SwapBuffersError,
}, },
reexports::{ reexports::{
@ -54,26 +59,39 @@ pub fn run_x11(log: Logger) {
let mut event_loop = EventLoop::try_new().unwrap(); let mut event_loop = EventLoop::try_new().unwrap();
let display = Rc::new(RefCell::new(Display::new())); let display = Rc::new(RefCell::new(Display::new()));
let mut backend = X11Backend::with_title("Anvil", log.clone()).expect("Failed to initialize X11 backend"); let backend = X11Backend::new(log.clone()).expect("Failed to initilize X11 backend");
let handle = backend.handle();
// Obtain the DRM node the X server uses for direct rendering. // Obtain the DRM node the X server uses for direct rendering.
let drm_node = backend let drm_node = handle
.drm_node() .drm_node()
.expect("Could not get DRM node used by X server"); .expect("Could not get DRM node used by X server");
// Create the gbm device for buffer allocation and the X11 surface which presents to the window. // Create the gbm device for buffer allocation.
let device = gbm::Device::new(drm_node).expect("Failed to create gbm device"); let device = gbm::Device::new(drm_node).expect("Failed to create gbm device");
// Initialize EGL using the GBM device setup earlier. // Initialize EGL using the GBM device.
let egl = EGLDisplay::new(&device, log.clone()).expect("Failed to create EGLDisplay"); let egl = EGLDisplay::new(&device, log.clone()).expect("Failed to create EGLDisplay");
// Create the OpenGL context
let context = EGLContext::new(&egl, log.clone()).expect("Failed to create EGLContext"); let context = EGLContext::new(&egl, log.clone()).expect("Failed to create EGLContext");
let surface = X11Surface::new(
&mut backend, let window = WindowBuilder::new()
device, .title("Anvil")
context .build(&handle)
.dmabuf_render_formats() .expect("Failed to create first window");
.iter()
.map(|format| format.modifier), let device = Arc::new(Mutex::new(device));
)
.expect("Failed to create X11 surface"); // Create the surface for the window.
let surface = handle
.create_surface(
&window,
device,
context
.dmabuf_render_formats()
.iter()
.map(|format| format.modifier),
)
.expect("Failed to create X11 surface");
let renderer = let renderer =
unsafe { Gles2Renderer::new(context, log.clone()) }.expect("Failed to initialize renderer"); unsafe { Gles2Renderer::new(context, log.clone()) }.expect("Failed to initialize renderer");
@ -98,8 +116,6 @@ pub fn run_x11(log: Logger) {
} }
} }
let window = backend.window();
let size = { let size = {
let s = window.size(); let s = window.size();

View File

@ -22,6 +22,12 @@ pub mod dumb;
pub mod gbm; pub mod gbm;
mod swapchain; mod swapchain;
use std::{
cell::RefCell,
rc::Rc,
sync::{Arc, Mutex},
};
use crate::utils::{Buffer as BufferCoords, Size}; use crate::utils::{Buffer as BufferCoords, Size};
pub use swapchain::{Slot, Swapchain}; pub use swapchain::{Slot, Swapchain};
@ -60,3 +66,34 @@ pub trait Allocator<B: Buffer> {
modifiers: &[Modifier], modifiers: &[Modifier],
) -> Result<B, Self::Error>; ) -> Result<B, Self::Error>;
} }
// General implementations for interior mutability.
impl<A: Allocator<B>, B: Buffer> Allocator<B> for Arc<Mutex<A>> {
type Error = A::Error;
fn create_buffer(
&mut self,
width: u32,
height: u32,
fourcc: Fourcc,
modifiers: &[Modifier],
) -> Result<B, Self::Error> {
let mut guard = self.lock().unwrap();
guard.create_buffer(width, height, fourcc, modifiers)
}
}
impl<A: Allocator<B>, B: Buffer> Allocator<B> for Rc<RefCell<A>> {
type Error = A::Error;
fn create_buffer(
&mut self,
width: u32,
height: u32,
fourcc: Fourcc,
modifiers: &[Modifier],
) -> Result<B, Self::Error> {
self.borrow_mut().create_buffer(width, height, fourcc, modifiers)
}
}

View File

@ -25,10 +25,17 @@ pub enum X11Error {
#[error("Creating the window failed")] #[error("Creating the window failed")]
CreateWindow(CreateWindowError), CreateWindow(CreateWindowError),
/// An X11 surface already exists for this backend. /// An X11 surface already exists for this window.
#[error("An X11 surface already exists for this backend")] #[error("An X11 surface already exists for this window")]
SurfaceExists, SurfaceExists,
/// An invalid window was used to create an X11 surface.
///
/// This error will be risen if the window was destroyed or the window does not belong to the [`X11Handle`](super::X11Handle)
/// in use.
#[error("An invalid window was used to create an X11 surface")]
InvalidWindow,
/// The X server is not capable of direct rendering. /// The X server is not capable of direct rendering.
#[error("The X server is not capable of direct rendering")] #[error("The X server is not capable of direct rendering")]
CannotDirectRender, CannotDirectRender,

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@ use super::{extension::Extensions, Atoms, Window, X11Error};
use drm_fourcc::DrmFourcc; use drm_fourcc::DrmFourcc;
use std::sync::{ use std::sync::{
atomic::{AtomicU32, AtomicU64}, atomic::{AtomicU32, AtomicU64},
mpsc::Sender,
Arc, Mutex, Weak, Arc, Mutex, Weak,
}; };
use x11rb::{ use x11rb::{
@ -60,6 +61,10 @@ pub(crate) struct WindowInner {
pub atoms: Atoms, pub atoms: Atoms,
pub cursor_state: Arc<Mutex<CursorState>>, pub cursor_state: Arc<Mutex<CursorState>>,
pub size: Mutex<Size<u16, Logical>>, pub size: Mutex<Size<u16, Logical>>,
/// Channel used to send resize notifications to the surface that presents to this window.
///
/// This value will be [`None`] if no surface is bound to the window.
pub resize: Mutex<Option<Sender<Size<u16, Logical>>>>,
pub next_serial: AtomicU32, pub next_serial: AtomicU32,
pub last_msc: Arc<AtomicU64>, pub last_msc: Arc<AtomicU64>,
pub format: DrmFourcc, pub format: DrmFourcc,
@ -154,6 +159,7 @@ impl WindowInner {
format, format,
depth, depth,
extensions, extensions,
resize: Mutex::new(None),
}; };
// Enable WM_DELETE_WINDOW so our client is not disconnected upon our toplevel window being destroyed. // Enable WM_DELETE_WINDOW so our client is not disconnected upon our toplevel window being destroyed.