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`
- `X11Surface::buffer` now additionally returns the age of the buffer
- `X11Surface` now has an explicit `submit` function
- `X11Surface` is now multi-window capable.
### 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;
#[cfg(feature = "egl")]
@ -7,7 +12,7 @@ use smithay::{
backend::{
egl::{EGLContext, EGLDisplay},
renderer::{gles2::Gles2Renderer, Bind, ImportEgl, Renderer, Transform, Unbind},
x11::{X11Backend, X11Event, X11Surface},
x11::{WindowBuilder, X11Backend, X11Event, X11Surface},
SwapBuffersError,
},
reexports::{
@ -54,26 +59,39 @@ pub fn run_x11(log: Logger) {
let mut event_loop = EventLoop::try_new().unwrap();
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.
let drm_node = backend
let drm_node = handle
.drm_node()
.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");
// 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");
// Create the OpenGL context
let context = EGLContext::new(&egl, log.clone()).expect("Failed to create EGLContext");
let surface = X11Surface::new(
&mut backend,
device,
context
.dmabuf_render_formats()
.iter()
.map(|format| format.modifier),
)
.expect("Failed to create X11 surface");
let window = WindowBuilder::new()
.title("Anvil")
.build(&handle)
.expect("Failed to create first window");
let device = Arc::new(Mutex::new(device));
// 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 =
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 s = window.size();

View File

@ -22,6 +22,12 @@ pub mod dumb;
pub mod gbm;
mod swapchain;
use std::{
cell::RefCell,
rc::Rc,
sync::{Arc, Mutex},
};
use crate::utils::{Buffer as BufferCoords, Size};
pub use swapchain::{Slot, Swapchain};
@ -60,3 +66,34 @@ pub trait Allocator<B: Buffer> {
modifiers: &[Modifier],
) -> 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")]
CreateWindow(CreateWindowError),
/// An X11 surface already exists for this backend.
#[error("An X11 surface already exists for this backend")]
/// An X11 surface already exists for this window.
#[error("An X11 surface already exists for this window")]
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.
#[error("The X server is not capable of direct rendering")]
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 std::sync::{
atomic::{AtomicU32, AtomicU64},
mpsc::Sender,
Arc, Mutex, Weak,
};
use x11rb::{
@ -60,6 +61,10 @@ pub(crate) struct WindowInner {
pub atoms: Atoms,
pub cursor_state: Arc<Mutex<CursorState>>,
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 last_msc: Arc<AtomicU64>,
pub format: DrmFourcc,
@ -154,6 +159,7 @@ impl WindowInner {
format,
depth,
extensions,
resize: Mutex::new(None),
};
// Enable WM_DELETE_WINDOW so our client is not disconnected upon our toplevel window being destroyed.