x11: allocate buffers using gbm with modifiers

This commit is contained in:
i509VCB 2021-11-04 17:15:26 -05:00 committed by Victor Brekenfeld
parent 53d43905ac
commit 86716f9c9f
3 changed files with 40 additions and 41 deletions

View File

@ -62,12 +62,19 @@ pub fn run_x11(log: Logger) {
// Create the gbm device for buffer allocation and the X11 surface which presents to the window.
let device = gbm::Device::new(drm_node).expect("Failed to create gbm device");
let format = backend.format();
let surface = X11Surface::new(&mut backend, device, format).expect("Failed to create X11 surface");
// Initialize EGL using the GBM device setup earlier.
let egl = EGLDisplay::new(&surface, log.clone()).expect("Failed to create EGLDisplay");
let egl = EGLDisplay::new(&device, log.clone()).expect("Failed to create EGLDisplay");
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 renderer =
unsafe { Gles2Renderer::new(context, log.clone()) }.expect("Failed to initialize renderer");
let renderer = Rc::new(RefCell::new(renderer));

View File

@ -16,9 +16,6 @@ use winit::{platform::unix::WindowExtUnix, window::Window as WinitWindow};
#[cfg(feature = "backend_gbm")]
use gbm::{AsRaw, Device as GbmDevice};
#[cfg(feature = "backend_x11")]
use crate::backend::x11::X11Surface;
/// Create a `EGLPlatform<'a>` for the provided platform.
///
/// # Arguments
@ -168,27 +165,6 @@ impl EGLNativeDisplay for WinitWindow {
}
}
#[cfg(feature = "backend_x11")]
impl EGLNativeDisplay for X11Surface {
fn supported_platforms(&self) -> Vec<EGLPlatform<'_>> {
vec![
// todo: https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_platform_device.txt
// see: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_platform_gbm.txt
egl_platform!(
PLATFORM_GBM_KHR,
self.device().as_raw(),
&["EGL_KHR_platform_gbm"]
),
// see: https://www.khronos.org/registry/EGL/extensions/MESA/EGL_MESA_platform_gbm.txt
egl_platform!(
PLATFORM_GBM_MESA,
self.device().as_raw(),
&["EGL_MESA_platform_gbm"]
),
]
}
}
/// Shallow type for EGL_PLATFORM_X11_EXT with the default X11 display
#[derive(Debug)]
pub struct X11DefaultDisplay;

View File

@ -14,8 +14,9 @@
//! ```rust,no_run
//! # use std::error::Error;
//! # use smithay::backend::x11::{X11Backend, X11Surface};
//! use smithay::backend::allocator::Fourcc;
//! use smithay::backend::egl::{EGLDisplay, EGLContext};
//! use smithay::reexports::gbm;
//! use std::collections::HashSet;
//!
//! # struct CompositorState;
//! fn init_x11_backend(
@ -23,7 +24,7 @@
//! logger: slog::Logger
//! ) -> Result<(), Box<dyn Error>> {
//! // Create the backend, also yielding a surface that may be used to render to the window.
//! let mut backend = X11Backend::new(logger)?;
//! let mut backend = X11Backend::new(logger.clone())?;
//! // You can get a handle to the window the backend has created for later use.
//! let window = backend.window();
//!
@ -33,13 +34,14 @@
//! let drm_node = backend.drm_node()?;
//! // Create the gbm device for allocating buffers
//! let device = gbm::Device::new(drm_node)?;
//! // Initialize EGL to retrieve the support modifier list
//! let egl = EGLDisplay::new(&device, logger.clone()).expect("Failed to create EGLDisplay");
//! let context = EGLContext::new(&egl, logger).expect("Failed to create EGLContext");
//! let modifiers = context.dmabuf_render_formats().iter().map(|format| format.modifier).collect::<HashSet<_>>();
//!
//! // Finally create the X11 surface, you will use this to obtain buffers that will be presented to the
//! // window.
//!
//! // It is more than likely you will want more robust format detection rather than forcing `Argb8888`,
//! // but that is outside of the scope of the example.
//! let surface = X11Surface::new(&mut backend, device, Fourcc::Argb8888);
//! let surface = X11Surface::new(&mut backend, device, modifiers.into_iter());
//!
//! // Insert the backend into the event loop to receive events.
//! handle.insert_source(backend, |event, _window, state| {
@ -82,7 +84,7 @@ use crate::{
utils::{x11rb::X11Source, Logical, Size},
};
use calloop::{EventSource, Poll, PostAction, Readiness, Token, TokenFactory};
use drm_fourcc::DrmFourcc;
use drm_fourcc::{DrmFourcc, DrmModifier};
use gbm::{BufferObject, BufferObjectFlags};
use nix::{
fcntl::{self, OFlag},
@ -440,22 +442,36 @@ impl X11Surface {
pub fn new(
backend: &mut X11Backend,
device: gbm::Device<DrmNode>,
format: DrmFourcc,
modifiers: impl Iterator<Item = DrmModifier>,
) -> Result<X11Surface, X11Error> {
if backend.resize.is_some() {
return Err(X11Error::SurfaceExists);
}
let size = backend.window().size();
let modifiers = modifiers.collect::<Vec<_>>();
let window = backend.window();
let format = window.format().unwrap();
let size = window.size();
let mut current = device
.create_buffer_object(size.w as u32, size.h as u32, format, BufferObjectFlags::empty())
.create_buffer_object_with_modifiers(
size.w as u32,
size.h as u32,
format,
modifiers.iter().cloned(),
)
.map_err(Into::<AllocateBuffersError>::into)?;
current
.set_userdata(current.export().map_err(Into::<AllocateBuffersError>::into)?)
.map_err(Into::<AllocateBuffersError>::into)?;
let mut next = device
.create_buffer_object(size.w as u32, size.h as u32, format, BufferObjectFlags::empty())
.create_buffer_object_with_modifiers(
size.w as u32,
size.h as u32,
format,
modifiers.iter().cloned(),
)
.map_err(Into::<AllocateBuffersError>::into)?;
next.set_userdata(next.export().map_err(Into::<AllocateBuffersError>::into)?)
.map_err(Into::<AllocateBuffersError>::into)?;
@ -466,7 +482,7 @@ impl X11Surface {
Ok(X11Surface {
connection: Arc::downgrade(&backend.connection),
window: backend.window(),
window,
device,
format,
width: size.w,