Skip to content

Commit

Permalink
wayland(dmabuf): ImportNotifier for asyncrohnous buffer import
Browse files Browse the repository at this point in the history
  • Loading branch information
i509VCB committed Nov 13, 2023
1 parent a8f3c46 commit b1ecb8e
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 111 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ drm-ffi = { version = "0.6.0", optional = true }
errno = "0.3.5"
gbm = { version = "0.13.0", optional = true, default-features = false, features = ["drm-support"] }
glow = { version = "0.12", optional = true }
glutin = { version = "0.31.1", optional = true }
input = { version = "0.8.2", default-features = false, features=["libinput_1_14"], optional = true }
indexmap = "2.0"
lazy_static = "1"
Expand Down Expand Up @@ -88,7 +89,7 @@ backend_drm = ["drm", "drm-ffi"]
backend_gbm = ["gbm", "cc", "pkg-config"]
backend_gbm_has_fd_for_plane = []
backend_gbm_has_create_with_modifiers2 = []
backend_egl = ["gl_generator", "libloading"]
backend_egl = ["gl_generator", "libloading", "glutin"]
backend_libinput = ["input"]
backend_session = []
backend_udev = ["udev", "input/udev"]
Expand Down
13 changes: 8 additions & 5 deletions anvil/src/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ use smithay::{
wayland::{
compositor,
dmabuf::{
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState, ImportError,
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier,
},
drm_lease::{
DrmLease, DrmLeaseBuilder, DrmLeaseHandler, DrmLeaseRequest, DrmLeaseState, LeaseRejected,
Expand Down Expand Up @@ -156,13 +156,16 @@ impl DmabufHandler for AnvilState<UdevData> {
&mut self.backend_data.dmabuf_state.as_mut().unwrap().0
}

fn dmabuf_imported(&mut self, _global: &DmabufGlobal, dmabuf: Dmabuf) -> Result<(), ImportError> {
self.backend_data
fn dmabuf_imported(&mut self, _global: &DmabufGlobal, dmabuf: Dmabuf, notifier: ImportNotifier) {
if self
.backend_data
.gpus
.single_renderer(&self.backend_data.primary_gpu)
.and_then(|mut renderer| renderer.import_dmabuf(&dmabuf, None))
.map(|_| ())
.map_err(|_| ImportError::Failed)
.is_err()
{
notifier.failed();
}
}
}
delegate_dmabuf!(AnvilState<UdevData>);
Expand Down
13 changes: 8 additions & 5 deletions anvil/src/winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use smithay::{
wayland::{
compositor,
dmabuf::{
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState, ImportError,
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier,
},
},
};
Expand All @@ -64,13 +64,16 @@ impl DmabufHandler for AnvilState<WinitData> {
&mut self.backend_data.dmabuf_state.0
}

fn dmabuf_imported(&mut self, _global: &DmabufGlobal, dmabuf: Dmabuf) -> Result<(), ImportError> {
self.backend_data
fn dmabuf_imported(&mut self, _global: &DmabufGlobal, dmabuf: Dmabuf, notifier: ImportNotifier) {
if self
.backend_data
.backend
.renderer()
.import_dmabuf(&dmabuf, None)
.map(|_| ())
.map_err(|_| ImportError::Failed)
.is_err()
{
notifier.failed();
}
}
}
delegate_dmabuf!(AnvilState<WinitData>);
Expand Down
12 changes: 5 additions & 7 deletions anvil/src/x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use smithay::{
wayland::{
compositor,
dmabuf::{
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState, ImportError,
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier,
},
},
};
Expand Down Expand Up @@ -73,12 +73,10 @@ impl DmabufHandler for AnvilState<X11Data> {
&mut self.backend_data.dmabuf_state
}

fn dmabuf_imported(&mut self, _global: &DmabufGlobal, dmabuf: Dmabuf) -> Result<(), ImportError> {
self.backend_data
.renderer
.import_dmabuf(&dmabuf, None)
.map(|_| ())
.map_err(|_| ImportError::Failed)
fn dmabuf_imported(&mut self, _global: &DmabufGlobal, dmabuf: Dmabuf, notifier: ImportNotifier) {
if self.backend_data.renderer.import_dmabuf(&dmabuf, None).is_err() {
notifier.failed();
}
}
}
delegate_dmabuf!(AnvilState<X11Data>);
Expand Down
76 changes: 23 additions & 53 deletions src/wayland/dmabuf/dispatch.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::sync::{atomic::AtomicBool, Mutex};

use tracing::error;

use wayland_protocols::wp::linux_dmabuf::zv1::server::{
zwp_linux_buffer_params_v1, zwp_linux_dmabuf_feedback_v1, zwp_linux_dmabuf_v1,
};
Expand All @@ -16,7 +14,7 @@ use crate::{

use super::{
DmabufData, DmabufFeedbackData, DmabufGlobal, DmabufGlobalData, DmabufHandler, DmabufParamsData,
DmabufState, ImportError, Modifier, SurfaceDmabufFeedbackState,
DmabufState, Import, ImportNotifier, Modifier, SurfaceDmabufFeedbackState,
};

impl<D> Dispatch<wl_buffer::WlBuffer, Dmabuf, D> for DmabufState
Expand Down Expand Up @@ -224,7 +222,7 @@ where
{
fn request(
state: &mut D,
client: &Client,
_client: &Client,
params: &zwp_linux_buffer_params_v1::ZwpLinuxBufferParamsV1,
request: zwp_linux_buffer_params_v1::Request,
data: &DmabufParamsData,
Expand Down Expand Up @@ -285,33 +283,15 @@ where
// create_dmabuf performs an implicit ensure_unused function call.
if let Some(dmabuf) = data.create_dmabuf(params, width, height, format, flags) {
if state.dmabuf_state().globals.get(&data.id).is_some() {
match state.dmabuf_imported(&DmabufGlobal { id: data.id }, dmabuf.clone()) {
Ok(_) => {
match client.create_resource::<wl_buffer::WlBuffer, Dmabuf, D>(dh, 1, dmabuf)
{
Ok(buffer) => {
params.created(&buffer);
}

Err(_) => {
error!("failed to create protocol object for \"create\" request");
// Failed to import since the buffer protocol object could not be created.
params.failed();
}
}
}

Err(ImportError::InvalidFormat) => {
params.post_error(
zwp_linux_buffer_params_v1::Error::InvalidFormat,
"format and plane combination are not valid",
);
}

Err(ImportError::Failed) => {
params.failed();
}
}
let notifier = ImportNotifier {
inner: params.clone(),
display: dh.clone(),
dmabuf: dmabuf.clone(),
import: Import::Falliable,
drop_ignore: false,
};

state.dmabuf_imported(&DmabufGlobal { id: data.id }, dmabuf, notifier);
} else {
// If the dmabuf global was destroyed, we cannot import any buffers.
params.failed();
Expand All @@ -330,28 +310,18 @@ where
// create_dmabuf performs an implicit ensure_unused function call.
if let Some(dmabuf) = data.create_dmabuf(params, width, height, format, flags) {
if state.dmabuf_state().globals.get(&data.id).is_some() {
match state.dmabuf_imported(&DmabufGlobal { id: data.id }, dmabuf.clone()) {
Ok(_) => {
// Import was successful, initialize the dmabuf data
data_init.init(buffer_id, dmabuf);
}

Err(ImportError::InvalidFormat) => {
params.post_error(
zwp_linux_buffer_params_v1::Error::InvalidFormat,
"format and plane combination are not valid",
);
}

Err(ImportError::Failed) => {
// Buffer import failed. The protocol documentation heavily implies killing the
// client is the right thing to do here.
params.post_error(
zwp_linux_buffer_params_v1::Error::InvalidWlBuffer,
"buffer import failed",
);
}
}
// The buffer isn't technically valid during data_init, but the client is not allowed to use the buffer until ready.
let buffer = data_init.init(buffer_id, dmabuf.clone());

let notifier = ImportNotifier {
inner: params.clone(),
display: dh.clone(),
dmabuf: dmabuf.clone(),
import: Import::Infallible(buffer),
drop_ignore: false,
};

state.dmabuf_imported(&DmabufGlobal { id: data.id }, dmabuf, notifier);
} else {
// Buffer import failed. The protocol documentation heavily implies killing the
// client is the right thing to do here.
Expand Down
Loading

0 comments on commit b1ecb8e

Please sign in to comment.