gbm: detect gbm_bo_get_fd_for_plane

When available or forced with feature
backend_gbm_has_fd_for_plane use fd_for_plane
which allows the use of multi planar formats
which expose multiple planes with different fds.
This commit is contained in:
Christian Meissl 2022-10-03 09:27:15 +02:00
parent 76a878698e
commit fe1f9f2057
4 changed files with 60 additions and 2 deletions

View file

@ -69,13 +69,15 @@ slog-term = "2.3"
[build-dependencies]
gl_generator = { version = "0.14", optional = true }
pkg-config = { version = "0.3.17", optional = true }
cc = { version = "1.0", optional = true }
[features]
default = ["backend_drm", "backend_gbm", "backend_libinput", "backend_udev", "backend_session_logind", "backend_x11", "backend_winit", "desktop", "renderer_gl", "renderer_multi", "xwayland", "wayland_frontend", "slog-stdlog", "backend_vulkan"]
backend_winit = ["winit", "backend_egl", "wayland-egl", "renderer_gl"]
backend_x11 = ["x11rb", "x11rb/dri3", "x11rb/xfixes", "x11rb/present", "x11rb_event_source", "backend_gbm", "backend_drm", "backend_egl"]
backend_drm = ["drm", "drm-ffi"]
backend_gbm = ["gbm"]
backend_gbm = ["gbm", "cc", "pkg-config"]
backend_gbm_has_fd_for_plane = []
backend_egl = ["gl_generator", "libloading"]
backend_libinput = ["input"]
backend_session = []

View file

@ -97,10 +97,35 @@ fn find_logind() {
}
}
#[cfg(all(feature = "backend_gbm", not(feature = "backend_gbm_has_fd_for_plane")))]
fn test_gbm_bo_fd_for_plane() {
let gbm = match pkg_config::probe_library("gbm") {
Ok(lib) => lib,
Err(_) => {
println!("cargo:warning=failed to find gbm, assuming gbm_bo_get_fd_for_plane is unavailable");
return;
}
};
let has_gbm_bo_get_fd_for_plane = cc::Build::new()
.file("test_gbm_bo_get_fd_for_plane.c")
.includes(gbm.include_paths)
.warnings_into_errors(true)
.try_compile("test_gbm_bo_get_fd_for_plane")
.is_ok();
if has_gbm_bo_get_fd_for_plane {
println!("cargo:rustc-cfg=feature=\"backend_gbm_has_fd_for_plane\"");
}
}
fn main() {
#[cfg(any(feature = "backend_egl", feature = "renderer_gl"))]
gl_generate();
#[cfg(feature = "backend_session_logind")]
find_logind();
#[cfg(all(feature = "backend_gbm", not(feature = "backend_gbm_has_fd_for_plane")))]
test_gbm_bo_fd_for_plane();
}

View file

@ -74,10 +74,36 @@ pub enum GbmConvertError {
impl<T> AsDmabuf for GbmBuffer<T> {
type Error = GbmConvertError;
#[cfg(feature = "backend_gbm_has_fd_for_plane")]
fn export(&self) -> Result<Dmabuf, GbmConvertError> {
let planes = self.plane_count()? as i32;
let mut builder = Dmabuf::builder_from_buffer(self, DmabufFlags::empty());
for idx in 0..planes {
let fd = self.fd_for_plane(idx)?;
// gbm_bo_get_fd_for_plane returns -1 if an error occurs
if fd == -1 {
return Err(GbmConvertError::InvalidFD);
}
builder.add_plane(
// SAFETY: `gbm_bo_get_fd_for_plane` returns a new fd owned by the caller.
unsafe { OwnedFd::from_raw_fd(fd) },
idx as u32,
self.offset(idx)?,
self.stride_for_plane(idx)?,
self.modifier()?,
);
}
Ok(builder.build().unwrap())
}
#[cfg(not(feature = "backend_gbm_has_fd_for_plane"))]
fn export(&self) -> Result<Dmabuf, GbmConvertError> {
let planes = self.plane_count()? as i32;
//TODO switch to gbm_bo_get_plane_fd when it lands
let mut iter = (0i32..planes).map(|i| self.handle_for_plane(i));
let first = iter.next().expect("Encountered a buffer with zero planes");
// check that all handles are the same

View file

@ -0,0 +1,5 @@
#include <gbm.h>
void test() {
gbm_bo_get_fd_for_plane(NULL, 0);
}