Skip to content

Commit

Permalink
[feat] refactored dmabuf->eglImage API into libwayshot
Browse files Browse the repository at this point in the history
  • Loading branch information
CheerfulPianissimo committed Aug 13, 2024
1 parent 8d410d7 commit 4d2c574
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 157 deletions.
5 changes: 4 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion libwayshot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ wayland-protocols = { version = "0.31.0", features = ["client", "unstable"] }
wayland-protocols-wlr = { version = "0.2.0", features = ["client"] }

gbm = "0.15.0"
drm = "0.12.0"
drm = "0.12.0"

gl = "0.14.0"
gl_loader = "0.1.2"
khronos-egl = { version = "6.0.0",features = ["static"] }
2 changes: 1 addition & 1 deletion libwayshot/examples/waymirror-egl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
gl = "0.14.0"
gl_loader = "0.1.2"
khronos-egl = { version = "6.0.0",features = ["dynamic"] }
khronos-egl = { version = "6.0.0",features = ["static"] }
thiserror = "1.0.58"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
Expand Down
131 changes: 8 additions & 123 deletions libwayshot/examples/waymirror-egl/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use crate::utils::load_shader;
use libwayshot::WayshotConnection;

use gl::types::{GLeglImageOES, GLuint};
use khronos_egl::{self as egl, Attrib, DynamicInstance, EGLClientBuffer};
use std::os::fd::{AsRawFd, IntoRawFd};
use khronos_egl::{self as egl};
use std::{ffi::c_void, rc::Rc};
use wayland_client::{
protocol::{wl_compositor, wl_display::WlDisplay, wl_surface::WlSurface},
Expand All @@ -25,7 +24,7 @@ pub struct WaylandEGLState {
pub wl_display: WlDisplay,
pub wl_surface: Option<WlSurface>,

pub egl: egl::DynamicInstance,
pub egl: egl::Instance<egl::Static>,
pub egl_window: Option<Rc<WlEglSurface>>,
pub egl_display: Option<egl::Display>,
pub egl_surface: Option<egl::Surface>,
Expand All @@ -47,12 +46,6 @@ impl WaylandEGLState {
#[tracing::instrument]
pub fn new() -> Result<Self, ConnectError> {
let server_connection = Connection::connect_to_env()?;
let lib =
unsafe { libloading::Library::new("libEGL.so.1").expect("unable to find libEGL.so.1") };
let egl = unsafe {
egl::DynamicInstance::<egl::EGL1_5>::load_required_from(lib)
.expect("unable to load libEGL.so.1")
};

Ok(Self {
width: 1920,
Expand All @@ -64,7 +57,7 @@ impl WaylandEGLState {
wl_display: server_connection.display(),
wl_surface: None,

egl: egl,
egl: khronos_egl::Instance::new(egl::Static),
egl_window: None,
egl_display: None,
egl_surface: None,
Expand Down Expand Up @@ -136,7 +129,6 @@ impl WaylandEGLState {
.egl
.choose_first_config(self.egl_display.unwrap(), &attributes)?
.expect("unable to find an appropriate EGL configuration");
dbg!(config);
self.egl_surface = Some(unsafe {
self.egl.create_window_surface(
self.egl_display.unwrap(),
Expand Down Expand Up @@ -222,12 +214,11 @@ impl WaylandEGLState {
unsafe {
gl::GenTextures(1, &mut self.gl_texture);

self.dmabuf_to_egl();
self.dmabuf_to_texture();

gl::GenVertexArrays(1, &mut vao as *mut u32);
gl::GenBuffers(1, &mut vbo as *mut u32);
gl::GenBuffers(1, &mut ebo as *mut u32);
dbg!(vbo, vao, ebo);
gl::BindVertexArray(vao);

gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
Expand Down Expand Up @@ -278,91 +269,20 @@ impl WaylandEGLState {
gl::ClearColor(1.0, 1.0, 0.0, 1.0);
gl::Clear(gl::COLOR_BUFFER_BIT);
gl::DeleteTextures(1, &mut self.gl_texture);
self.dmabuf_to_egl();
self.dmabuf_to_texture();
gl::UseProgram(self.gl_program);
//gl::BindTexture(gl::TEXTURE_2D, self.gl_texture);
//gl::BindVertexArray(1);
gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, 0 as *const c_void);
}
}

pub fn dmabuf_to_egl(&self) {
type Attrib = egl::Attrib;
let (frame_format, guard, bo) = self
pub fn dmabuf_to_texture(&self) {
let image = self
.wayshot
.capture_output_frame_dmabuf(true, &self.wayshot.get_all_outputs()[0].wl_output, None)
.capture_output_frame_eglimage(true, &self.wayshot.get_all_outputs()[0].wl_output, None)
.unwrap();
self.egl_window.as_ref().unwrap().resize(
frame_format.size.width as i32,
frame_format.size.height as i32,
0,
0,
);
unsafe {
gl::Viewport(
0,
0,
frame_format.size.width as i32,
frame_format.size.height as i32,
)
};
// let modifier: u64 = dbg!(bo.modifier().unwrap().into());
// dbg!(bo.plane_count().unwrap());
let image_attribs = [
egl::WIDTH as Attrib,
frame_format.size.width as Attrib,
egl::HEIGHT as Attrib,
frame_format.size.height as Attrib,
0x3271, //EGL_LINUX_DRM_FOURCC_EXT
bo.format().unwrap() as Attrib,
0x3272, //EGL_DMA_BUF_PLANE0_FD_EXT
bo.fd_for_plane(0).unwrap().into_raw_fd() as Attrib,
0x3273, //EGL_DMA_BUF_PLANE0_OFFSET_EXT
bo.offset(0).unwrap() as Attrib,
0x3274, //EGL_DMA_BUF_PLANE0_PITCH_EXT
bo.stride_for_plane(0).unwrap() as Attrib,
// 0x3443, //EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT
// (modifier as u32) as Attrib,
// 0x3444, //EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT
// (modifier >> 32) as Attrib,
egl::ATTRIB_NONE as Attrib,
];

// self.wl_surface
// .as_ref()
// .unwrap()
// .attach(Some(&guard.buffer), 0, 0);
// self.wl_surface.as_ref().unwrap().commit();
// let wlbuf = guard.buffer.id().as_ptr();
// dbg!(image_attribs, image_attribs.len());
unsafe {
// let egl_create_image_khr: unsafe extern "system" fn(
// display: khronos_egl::EGLDisplay,
// ctx: khronos_egl::EGLContext,
// target: khronos_egl::Enum,
// buffer: khronos_egl::EGLClientBuffer,
// attrib_list: *const Attrib,
// )
// -> khronos_egl::EGLImage =
// std::mem::transmute(dbg!(self.egl.get_proc_address("eglCreateImage").unwrap()));
// let image = egl_create_image_khr(
// self.egl_display.unwrap().as_ptr(),
// egl::NO_CONTEXT,
// 0x3270,
// std::ptr::null_mut() as EGLClientBuffer,
// image_attribs.as_ptr(),
// );
let image = self
.egl
.create_image(
self.egl_display.unwrap(),
khronos_egl::Context::from_ptr(egl::NO_CONTEXT),
0x3270, // EGL_LINUX_DMA_BUF_EXT
khronos_egl::ClientBuffer::from_ptr(std::ptr::null_mut()), //NULL
&image_attribs,
)
.unwrap();
//dbg!(image, self.egl.get_error());
let gl_egl_image_texture_target_2d_oes: unsafe extern "system" fn(
target: gl::types::GLenum,
image: GLeglImageOES,
Expand All @@ -380,42 +300,7 @@ impl WaylandEGLState {
self.egl
.destroy_image(self.egl_display.unwrap(), image)
.unwrap();

// let image_wl_attribs = [
// 0x31D6 as Attrib, //EGL_WAYLAND_PLANE_WL
// 0 as Attrib,
// egl::ATTRIB_NONE as Attrib,
// ];
// let image = egl_create_image_khr(
// self.egl_display.unwrap().as_ptr(),
// egl::NO_CONTEXT as *mut c_void,
// 0x31D5, //EGL_WAYLAND_BUFFER_WL,
// wlbuf as *mut c_void,
// image_wl_attribs.as_ptr(),
// );
// dbg!(image, self.egl.get_error());
//assert_ne!(image, 0 as *mut c_void);
// self.egl
// .create_image(
// self.egl_display.unwrap(),
// khronos_egl::Context::from_ptr(egl::NO_CONTEXT),
// 0x31D5, //EGL_WAYLAND_BUFFER_WL,
// khronos_egl::ClientBuffer::from_ptr(wlbuf.display_ptr() as *mut c_void), //NULL
// &image_wl_attribs,
// )
// .unwrap();
}
// self.egl_image = Some(unsafe {
// self.egl
// .create_image(
// self.egl_display.unwrap(),
// khronos_egl::Context::from_ptr(egl::NO_CONTEXT),
// 0x3270, // EGL_LINUX_DMA_BUF_EXT
// ClientBuffer::from_ptr(std::ptr::null_mut()), //NULL
// &image_attribs,
// )
// .unwrap()
// });
}

pub fn validate_globals(&self) -> Result<()> {
Expand Down
26 changes: 26 additions & 0 deletions libwayshot/src/dispatch.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{
collections::HashSet,
os::fd::{AsFd, BorrowedFd},
sync::atomic::{AtomicBool, Ordering},
};
use wayland_client::{
Expand Down Expand Up @@ -327,3 +328,28 @@ impl wayland_client::Dispatch<ZwlrLayerSurfaceV1, WlOutput> for LayerShellState
}
}
}
pub(crate) struct Card(std::fs::File);

/// Implementing [`AsFd`] is a prerequisite to implementing the traits found
/// in this crate. Here, we are just calling [`File::as_fd()`] on the inner
/// [`File`].
impl AsFd for Card {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}
impl drm::Device for Card {}
/// Simple helper methods for opening a `Card`.
impl Card {
pub fn open(path: &str) -> Self {
let mut options = std::fs::OpenOptions::new();
options.read(true);
options.write(true);
Card(options.open(path).unwrap())
}
}
#[derive(Debug)]
pub(crate) struct DMABUFState {
pub linux_dmabuf: ZwpLinuxDmabufV1,
pub gbmdev: gbm::Device<Card>,
}
6 changes: 4 additions & 2 deletions libwayshot/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ pub enum Error {
NoDMAStateError,
#[error("dmabuf color format provided by compositor is invalid")]
UnrecognizedColorCode(#[from] UnrecognizedFourcc),
#[error("dmabuf device is destroyed")]
#[error("dmabuf device has been destroyed")]
DRMDeviceLost(#[from] DeviceDestroyedError),
#[error("obtaining gbm buffer object file descriptor failed")]
#[error("obtaining gbm buffer object file descriptor failed {0}")]
GBMBoFdError(#[from] FdError),
#[error(" EGLImage import from dmabuf failed: {0}")]
EGLError(#[from] khronos_egl::Error),
}
Loading

0 comments on commit 4d2c574

Please sign in to comment.