Merge pull request #783 from mahkoh/jorth/sync-file-surface
wl_surface: add jay_sync_file_surface extension
This commit is contained in:
commit
fe8b51ffb6
13 changed files with 424 additions and 24 deletions
|
|
@ -24,6 +24,7 @@ use {
|
||||||
jay_tree_query::JayTreeQuery,
|
jay_tree_query::JayTreeQuery,
|
||||||
jay_workspace_watcher::JayWorkspaceWatcher,
|
jay_workspace_watcher::JayWorkspaceWatcher,
|
||||||
jay_xwayland::JayXwayland,
|
jay_xwayland::JayXwayland,
|
||||||
|
wl_surface::jay_sync_file_surface::JaySyncFileSurface,
|
||||||
},
|
},
|
||||||
leaks::Tracker,
|
leaks::Tracker,
|
||||||
object::{Object, Version},
|
object::{Object, Version},
|
||||||
|
|
@ -76,7 +77,7 @@ global_base!(JayCompositorGlobal, JayCompositor, JayCompositorError);
|
||||||
|
|
||||||
impl Global for JayCompositorGlobal {
|
impl Global for JayCompositorGlobal {
|
||||||
fn version(&self) -> u32 {
|
fn version(&self) -> u32 {
|
||||||
25
|
26
|
||||||
}
|
}
|
||||||
|
|
||||||
fn required_caps(&self) -> ClientCaps {
|
fn required_caps(&self) -> ClientCaps {
|
||||||
|
|
@ -520,6 +521,18 @@ impl JayCompositorRequestHandler for JayCompositor {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_sync_file_surface(
|
||||||
|
&self,
|
||||||
|
req: GetSyncFileSurface,
|
||||||
|
_slf: &Rc<Self>,
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
let surface = self.client.lookup(req.surface)?;
|
||||||
|
let obj = Rc::new(JaySyncFileSurface::new(req.id, self.version, &surface));
|
||||||
|
track!(self.client, obj);
|
||||||
|
self.client.add_client_obj(&obj)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object_base! {
|
object_base! {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ pub mod commit_timeline;
|
||||||
pub mod cursor;
|
pub mod cursor;
|
||||||
pub mod dnd_icon;
|
pub mod dnd_icon;
|
||||||
pub mod ext_session_lock_surface_v1;
|
pub mod ext_session_lock_surface_v1;
|
||||||
|
pub mod jay_sync_file_release;
|
||||||
|
pub mod jay_sync_file_surface;
|
||||||
pub mod tray;
|
pub mod tray;
|
||||||
pub mod wl_subsurface;
|
pub mod wl_subsurface;
|
||||||
pub mod wp_alpha_modifier_surface_v1;
|
pub mod wp_alpha_modifier_surface_v1;
|
||||||
|
|
@ -31,7 +33,7 @@ use {
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
AlphaMode, AsyncShmGfxTexture, BufferResv, BufferResvUser, FdSync, GfxError,
|
AlphaMode, AsyncShmGfxTexture, BufferResv, BufferResvUser, FdSync, GfxError,
|
||||||
GfxStagingBuffer, ReleaseSync, SampleRect,
|
GfxStagingBuffer, ReleaseSync, SampleRect, SyncFile,
|
||||||
},
|
},
|
||||||
ifs::{
|
ifs::{
|
||||||
color_management::wp_color_management_surface_feedback_v1::WpColorManagementSurfaceFeedbackV1,
|
color_management::wp_color_management_surface_feedback_v1::WpColorManagementSurfaceFeedbackV1,
|
||||||
|
|
@ -52,6 +54,7 @@ use {
|
||||||
commit_timeline::{ClearReason, CommitTimeline, CommitTimelineError},
|
commit_timeline::{ClearReason, CommitTimeline, CommitTimelineError},
|
||||||
cursor::CursorSurface,
|
cursor::CursorSurface,
|
||||||
dnd_icon::DndIcon,
|
dnd_icon::DndIcon,
|
||||||
|
jay_sync_file_release::SyncFileRelease,
|
||||||
tray::TrayItemId,
|
tray::TrayItemId,
|
||||||
wl_subsurface::{PendingSubsurfaceData, SubsurfaceId, WlSubsurface},
|
wl_subsurface::{PendingSubsurfaceData, SubsurfaceId, WlSubsurface},
|
||||||
wp_alpha_modifier_surface_v1::WpAlphaModifierSurfaceV1,
|
wp_alpha_modifier_surface_v1::WpAlphaModifierSurfaceV1,
|
||||||
|
|
@ -90,7 +93,7 @@ use {
|
||||||
},
|
},
|
||||||
video::{
|
video::{
|
||||||
dmabuf::DMA_BUF_SYNC_READ,
|
dmabuf::DMA_BUF_SYNC_READ,
|
||||||
drm::syncobj::{Syncobj, SyncobjPoint},
|
drm::syncobj::{Syncobj, SyncobjPoint, merge_sync_files},
|
||||||
},
|
},
|
||||||
wire::{
|
wire::{
|
||||||
WlOutputId, WlSurfaceId, WpColorManagementSurfaceFeedbackV1Id, ZwpIdleInhibitorV1Id,
|
WlOutputId, WlSurfaceId, WpColorManagementSurfaceFeedbackV1Id, ZwpIdleInhibitorV1Id,
|
||||||
|
|
@ -219,11 +222,20 @@ pub struct SurfaceBuffer {
|
||||||
pub release_sync: ReleaseSync,
|
pub release_sync: ReleaseSync,
|
||||||
release: Option<SyncobjRelease>,
|
release: Option<SyncobjRelease>,
|
||||||
_surface_release: SmallVec<[SurfaceRelease; 1]>,
|
_surface_release: SmallVec<[SurfaceRelease; 1]>,
|
||||||
|
sync_file_release: Option<SyncFileRelease>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for SurfaceBuffer {
|
impl Drop for SurfaceBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let syncs = self.syncs.take();
|
let syncs = self.syncs.take();
|
||||||
|
if let Some(release) = &mut self.sync_file_release {
|
||||||
|
let sync_file = merge_sync_files(syncs.iter().flat_map(|f| f.1.get_sync_file()))
|
||||||
|
.unwrap_or_else(|e| {
|
||||||
|
log::error!("Could not merge sync files: {}", ErrorFmt(e));
|
||||||
|
None
|
||||||
|
});
|
||||||
|
release.done(sync_file.as_ref());
|
||||||
|
}
|
||||||
if let Some(release) = &mut self.release {
|
if let Some(release) = &mut self.release {
|
||||||
release.signal(Some(&syncs));
|
release.signal(Some(&syncs));
|
||||||
return;
|
return;
|
||||||
|
|
@ -456,8 +468,10 @@ struct PendingState {
|
||||||
subsurfaces: AHashMap<SubsurfaceId, AttachedSubsurfaceState>,
|
subsurfaces: AHashMap<SubsurfaceId, AttachedSubsurfaceState>,
|
||||||
acquire_point: Option<(Rc<Syncobj>, SyncobjPoint)>,
|
acquire_point: Option<(Rc<Syncobj>, SyncobjPoint)>,
|
||||||
release_point: Option<SyncobjRelease>,
|
release_point: Option<SyncobjRelease>,
|
||||||
|
sync_file_acquire: Option<Option<SyncFile>>,
|
||||||
|
sync_file_release: Option<SyncFileRelease>,
|
||||||
alpha_multiplier: Option<Option<f32>>,
|
alpha_multiplier: Option<Option<f32>>,
|
||||||
explicit_sync: bool,
|
syncobj_sync: bool,
|
||||||
fifo_barrier_set: bool,
|
fifo_barrier_set: bool,
|
||||||
fifo_barrier_wait: bool,
|
fifo_barrier_wait: bool,
|
||||||
commit_time: Option<u64>,
|
commit_time: Option<u64>,
|
||||||
|
|
@ -485,8 +499,9 @@ impl PendingState {
|
||||||
self.buffer = Some(buffer);
|
self.buffer = Some(buffer);
|
||||||
self.acquire_point = next.acquire_point.take();
|
self.acquire_point = next.acquire_point.take();
|
||||||
self.release_point = next.release_point.take();
|
self.release_point = next.release_point.take();
|
||||||
self.explicit_sync = mem::take(&mut next.explicit_sync);
|
self.syncobj_sync = mem::take(&mut next.syncobj_sync);
|
||||||
self.surface_release = mem::take(&mut next.surface_release);
|
self.surface_release = mem::take(&mut next.surface_release);
|
||||||
|
self.sync_file_release = next.sync_file_release.take();
|
||||||
}
|
}
|
||||||
macro_rules! opt {
|
macro_rules! opt {
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
|
|
@ -510,6 +525,7 @@ impl PendingState {
|
||||||
opt!(color_description);
|
opt!(color_description);
|
||||||
opt!(serial);
|
opt!(serial);
|
||||||
opt!(alpha_mode);
|
opt!(alpha_mode);
|
||||||
|
opt!(sync_file_acquire);
|
||||||
{
|
{
|
||||||
let (dx1, dy1) = self.offset;
|
let (dx1, dy1) = self.offset;
|
||||||
let (dx2, dy2) = mem::take(&mut next.offset);
|
let (dx2, dy2) = mem::take(&mut next.offset);
|
||||||
|
|
@ -1094,16 +1110,20 @@ impl WlSurfaceRequestHandler for WlSurface {
|
||||||
let pending = &mut *self.pending.borrow_mut();
|
let pending = &mut *self.pending.borrow_mut();
|
||||||
if let Some(Some(buffer)) = &mut pending.buffer
|
if let Some(Some(buffer)) = &mut pending.buffer
|
||||||
&& pending.release_point.is_none()
|
&& pending.release_point.is_none()
|
||||||
|
&& pending.sync_file_release.is_none()
|
||||||
{
|
{
|
||||||
buffer.send_release = true;
|
buffer.send_release = true;
|
||||||
}
|
}
|
||||||
if let Some(release) = &mut pending.release_point {
|
if let Some(release) = &mut pending.release_point {
|
||||||
release.committed = true;
|
release.committed = true;
|
||||||
}
|
}
|
||||||
self.verify_explicit_sync(pending)?;
|
self.verify_syncobj_sync(pending)?;
|
||||||
if pending.surface_release.is_not_empty() && not_matches!(pending.buffer, Some(Some(_))) {
|
if pending.surface_release.is_not_empty() && not_matches!(pending.buffer, Some(Some(_))) {
|
||||||
return Err(WlSurfaceError::SurfaceReleaseWithoutAttach);
|
return Err(WlSurfaceError::SurfaceReleaseWithoutAttach);
|
||||||
}
|
}
|
||||||
|
if pending.sync_file_release.is_some() && not_matches!(pending.buffer, Some(Some(_))) {
|
||||||
|
return Err(WlSurfaceError::SyncFileReleaseWithoutAttach);
|
||||||
|
}
|
||||||
if ext.commit_requested(pending) == CommitAction::ContinueCommit {
|
if ext.commit_requested(pending) == CommitAction::ContinueCommit {
|
||||||
self.commit_timeline.commit(slf, pending)?;
|
self.commit_timeline.commit(slf, pending)?;
|
||||||
}
|
}
|
||||||
|
|
@ -1227,16 +1247,17 @@ impl WlSurface {
|
||||||
self.reset_shm_textures();
|
self.reset_shm_textures();
|
||||||
}
|
}
|
||||||
buffer.buf.update_texture_or_log(self, false);
|
buffer.buf.update_texture_or_log(self, false);
|
||||||
let release_sync = match pending.explicit_sync {
|
let mut release_sync = ReleaseSync::Implicit;
|
||||||
false => ReleaseSync::Implicit,
|
if pending.syncobj_sync || pending.sync_file_release.is_some() {
|
||||||
true => ReleaseSync::Explicit,
|
release_sync = ReleaseSync::Explicit;
|
||||||
};
|
}
|
||||||
let surface_buffer = SurfaceBuffer {
|
let surface_buffer = SurfaceBuffer {
|
||||||
buffer,
|
buffer,
|
||||||
syncs: Default::default(),
|
syncs: Default::default(),
|
||||||
release_sync,
|
release_sync,
|
||||||
release: pending.release_point.take(),
|
release: pending.release_point.take(),
|
||||||
_surface_release: mem::take(&mut pending.surface_release),
|
_surface_release: mem::take(&mut pending.surface_release),
|
||||||
|
sync_file_release: pending.sync_file_release.take(),
|
||||||
};
|
};
|
||||||
self.buffer.set(Some(Rc::new(surface_buffer)));
|
self.buffer.set(Some(Rc::new(surface_buffer)));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1542,9 +1563,9 @@ impl WlSurface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_explicit_sync(&self, pending: &mut PendingState) -> Result<(), WlSurfaceError> {
|
fn verify_syncobj_sync(&self, pending: &mut PendingState) -> Result<(), WlSurfaceError> {
|
||||||
pending.explicit_sync = self.syncobj_surface.is_some();
|
pending.syncobj_sync = self.syncobj_surface.is_some();
|
||||||
if !pending.explicit_sync {
|
if !pending.syncobj_sync {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let have_new_buffer = match &pending.buffer {
|
let have_new_buffer = match &pending.buffer {
|
||||||
|
|
@ -2171,6 +2192,8 @@ pub enum WlSurfaceError {
|
||||||
RegisterCommitTimeout(#[source] IoUringError),
|
RegisterCommitTimeout(#[source] IoUringError),
|
||||||
#[error("Content update contains release callbacks but no non-null buffer")]
|
#[error("Content update contains release callbacks but no non-null buffer")]
|
||||||
SurfaceReleaseWithoutAttach,
|
SurfaceReleaseWithoutAttach,
|
||||||
|
#[error("Content update contains sync file release but no non-null buffer")]
|
||||||
|
SyncFileReleaseWithoutAttach,
|
||||||
}
|
}
|
||||||
efrom!(WlSurfaceError, ClientError);
|
efrom!(WlSurfaceError, ClientError);
|
||||||
efrom!(WlSurfaceError, XdgSurfaceError);
|
efrom!(WlSurfaceError, XdgSurfaceError);
|
||||||
|
|
|
||||||
|
|
@ -203,18 +203,18 @@ impl CommitTimeline {
|
||||||
let mut collector = CommitDataCollector {
|
let mut collector = CommitDataCollector {
|
||||||
acquire_points: Default::default(),
|
acquire_points: Default::default(),
|
||||||
shm_uploads: 0,
|
shm_uploads: 0,
|
||||||
implicit_dmabufs: Default::default(),
|
acquire_files: Default::default(),
|
||||||
commit_time: Default::default(),
|
commit_time: Default::default(),
|
||||||
};
|
};
|
||||||
collector.collect(pending);
|
collector.collect(pending);
|
||||||
let points = collector.acquire_points;
|
let points = collector.acquire_points;
|
||||||
let pending_uploads = collector.shm_uploads;
|
let pending_uploads = collector.shm_uploads;
|
||||||
let implicit_dmabufs = collector.implicit_dmabufs;
|
let acquire_files = collector.acquire_files;
|
||||||
let commit_time = collector.commit_time;
|
let commit_time = collector.commit_time;
|
||||||
let has_commit_time = commit_time > 0;
|
let has_commit_time = commit_time > 0;
|
||||||
let has_dependencies = points.is_not_empty()
|
let has_dependencies = points.is_not_empty()
|
||||||
|| pending_uploads > 0
|
|| pending_uploads > 0
|
||||||
|| implicit_dmabufs.is_not_empty()
|
|| acquire_files.is_not_empty()
|
||||||
|| has_commit_time;
|
|| has_commit_time;
|
||||||
let must_be_queued = has_dependencies
|
let must_be_queued = has_dependencies
|
||||||
|| self.own_timeline.entries.is_not_empty()
|
|| self.own_timeline.entries.is_not_empty()
|
||||||
|
|
@ -242,7 +242,7 @@ impl CommitTimeline {
|
||||||
wait_handles: Cell::new(Default::default()),
|
wait_handles: Cell::new(Default::default()),
|
||||||
pending_uploads: NumCell::new(pending_uploads),
|
pending_uploads: NumCell::new(pending_uploads),
|
||||||
shm_upload: RefCell::new(ShmUploadState::None),
|
shm_upload: RefCell::new(ShmUploadState::None),
|
||||||
num_pending_polls: NumCell::new(implicit_dmabufs.len()),
|
num_pending_polls: NumCell::new(acquire_files.len()),
|
||||||
pending_polls: Cell::new(Default::default()),
|
pending_polls: Cell::new(Default::default()),
|
||||||
fifo_state: Cell::new(commit_fifo_state),
|
fifo_state: Cell::new(commit_fifo_state),
|
||||||
commit_times: RefCell::new(CommitTimesState::Ready),
|
commit_times: RefCell::new(CommitTimesState::Ready),
|
||||||
|
|
@ -270,9 +270,9 @@ impl CommitTimeline {
|
||||||
*commit.shm_upload.borrow_mut() = ShmUploadState::Todo(noderef.clone());
|
*commit.shm_upload.borrow_mut() = ShmUploadState::Todo(noderef.clone());
|
||||||
needs_flush = true;
|
needs_flush = true;
|
||||||
}
|
}
|
||||||
if implicit_dmabufs.is_not_empty() {
|
if acquire_files.is_not_empty() {
|
||||||
let mut pending_polls = SmallVec::new();
|
let mut pending_polls = SmallVec::new();
|
||||||
for fd in implicit_dmabufs {
|
for fd in acquire_files {
|
||||||
let handle = self
|
let handle = self
|
||||||
.shared
|
.shared
|
||||||
.ring
|
.ring
|
||||||
|
|
@ -692,7 +692,7 @@ type Point = (Rc<Syncobj>, SyncobjPoint);
|
||||||
struct CommitDataCollector {
|
struct CommitDataCollector {
|
||||||
acquire_points: SmallVec<[Point; 1]>,
|
acquire_points: SmallVec<[Point; 1]>,
|
||||||
shm_uploads: usize,
|
shm_uploads: usize,
|
||||||
implicit_dmabufs: SmallVec<[Rc<OwnedFd>; 1]>,
|
acquire_files: SmallVec<[Rc<OwnedFd>; 1]>,
|
||||||
commit_time: u64,
|
commit_time: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -703,14 +703,18 @@ impl CommitDataCollector {
|
||||||
if buffer.is_shm() {
|
if buffer.is_shm() {
|
||||||
self.shm_uploads += 1;
|
self.shm_uploads += 1;
|
||||||
}
|
}
|
||||||
if !pending.explicit_sync
|
if !pending.syncobj_sync
|
||||||
|
&& pending.sync_file_acquire.is_none()
|
||||||
&& let Some(dmabuf) = &buffer.client_dmabuf
|
&& let Some(dmabuf) = &buffer.client_dmabuf
|
||||||
{
|
{
|
||||||
for plane in &dmabuf.planes {
|
for plane in &dmabuf.planes {
|
||||||
self.implicit_dmabufs.push(plane.fd.clone());
|
self.acquire_files.push(plane.fd.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(Some(sf)) = pending.sync_file_acquire.take() {
|
||||||
|
self.acquire_files.push(sf.0);
|
||||||
|
}
|
||||||
if let Some(point) = pending.acquire_point.take() {
|
if let Some(point) = pending.acquire_point.take() {
|
||||||
self.acquire_points.push(point);
|
self.acquire_points.push(point);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
92
src/ifs/wl_surface/jay_sync_file_release.rs
Normal file
92
src/ifs/wl_surface/jay_sync_file_release.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
client::{Client, ClientError},
|
||||||
|
gfx_api::SyncFile,
|
||||||
|
leaks::Tracker,
|
||||||
|
object::{Object, Version},
|
||||||
|
wire::{JaySyncFileReleaseId, jay_sync_file_release::*},
|
||||||
|
},
|
||||||
|
std::{cell::Cell, rc::Rc},
|
||||||
|
thiserror::Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct SyncFileRelease {
|
||||||
|
pub release: Option<Rc<JaySyncFileRelease>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SyncFileRelease {
|
||||||
|
pub fn done(&mut self, sync_file: Option<&SyncFile>) {
|
||||||
|
if let Some(release) = self.release.take() {
|
||||||
|
release.done(sync_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for SyncFileRelease {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.done(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct JaySyncFileRelease {
|
||||||
|
pub id: JaySyncFileReleaseId,
|
||||||
|
pub client: Rc<Client>,
|
||||||
|
pub tracker: Tracker<Self>,
|
||||||
|
pub version: Version,
|
||||||
|
pub destroyed: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JaySyncFileRelease {
|
||||||
|
pub fn new(client: &Rc<Client>, id: JaySyncFileReleaseId, version: Version) -> Self {
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
client: client.clone(),
|
||||||
|
tracker: Default::default(),
|
||||||
|
version,
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn done(&self, sync_file: Option<&SyncFile>) {
|
||||||
|
if self.destroyed.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
match sync_file {
|
||||||
|
None => {
|
||||||
|
self.client.event(ReleaseImmediate { self_id: self.id });
|
||||||
|
}
|
||||||
|
Some(fd) => {
|
||||||
|
self.client.event(ReleaseAsync {
|
||||||
|
self_id: self.id,
|
||||||
|
sync_file: fd.0.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JaySyncFileReleaseRequestHandler for JaySyncFileRelease {
|
||||||
|
type Error = JaySyncFileReleaseError;
|
||||||
|
|
||||||
|
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
|
self.destroyed.set(true);
|
||||||
|
self.client.remove_obj(self)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object_base! {
|
||||||
|
self = JaySyncFileRelease;
|
||||||
|
version = self.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Object for JaySyncFileRelease {}
|
||||||
|
|
||||||
|
simple_add_obj!(JaySyncFileRelease);
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum JaySyncFileReleaseError {
|
||||||
|
#[error(transparent)]
|
||||||
|
ClientError(Box<ClientError>),
|
||||||
|
}
|
||||||
|
efrom!(JaySyncFileReleaseError, ClientError);
|
||||||
92
src/ifs/wl_surface/jay_sync_file_surface.rs
Normal file
92
src/ifs/wl_surface/jay_sync_file_surface.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
client::{Client, ClientError},
|
||||||
|
gfx_api::SyncFile,
|
||||||
|
ifs::wl_surface::{
|
||||||
|
WlSurface,
|
||||||
|
jay_sync_file_release::{JaySyncFileRelease, SyncFileRelease},
|
||||||
|
},
|
||||||
|
leaks::Tracker,
|
||||||
|
object::{Object, Version},
|
||||||
|
wire::{JaySyncFileSurfaceId, jay_sync_file_surface::*},
|
||||||
|
},
|
||||||
|
std::rc::Rc,
|
||||||
|
thiserror::Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct JaySyncFileSurface {
|
||||||
|
pub id: JaySyncFileSurfaceId,
|
||||||
|
pub client: Rc<Client>,
|
||||||
|
pub surface: Rc<WlSurface>,
|
||||||
|
pub tracker: Tracker<Self>,
|
||||||
|
pub version: Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JaySyncFileSurface {
|
||||||
|
pub fn new(id: JaySyncFileSurfaceId, version: Version, surface: &Rc<WlSurface>) -> Self {
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
client: surface.client.clone(),
|
||||||
|
surface: surface.clone(),
|
||||||
|
tracker: Default::default(),
|
||||||
|
version,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JaySyncFileSurfaceRequestHandler for JaySyncFileSurface {
|
||||||
|
type Error = JaySyncFileSurfaceError;
|
||||||
|
|
||||||
|
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
|
self.client.remove_obj(self)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_acquire_immediate(
|
||||||
|
&self,
|
||||||
|
_req: SetAcquireImmediate,
|
||||||
|
_slf: &Rc<Self>,
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
self.surface.pending.borrow_mut().sync_file_acquire = Some(None);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_acquire_async(&self, req: SetAcquireAsync, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
|
self.surface.pending.borrow_mut().sync_file_acquire = Some(Some(SyncFile(req.sync_file)));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_release(&self, req: GetRelease, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
|
let obj = Rc::new(JaySyncFileRelease::new(
|
||||||
|
&self.client,
|
||||||
|
req.release,
|
||||||
|
self.version,
|
||||||
|
));
|
||||||
|
track!(self.client, obj);
|
||||||
|
self.client.add_client_obj(&obj)?;
|
||||||
|
let pending = &mut *self.surface.pending.borrow_mut();
|
||||||
|
if pending.sync_file_release.is_some() {
|
||||||
|
return Err(JaySyncFileSurfaceError::HasRelease);
|
||||||
|
}
|
||||||
|
pending.sync_file_release = Some(SyncFileRelease { release: Some(obj) });
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object_base! {
|
||||||
|
self = JaySyncFileSurface;
|
||||||
|
version = self.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Object for JaySyncFileSurface {}
|
||||||
|
|
||||||
|
simple_add_obj!(JaySyncFileSurface);
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum JaySyncFileSurfaceError {
|
||||||
|
#[error(transparent)]
|
||||||
|
ClientError(Box<ClientError>),
|
||||||
|
#[error("The content update already has a release object")]
|
||||||
|
HasRelease,
|
||||||
|
}
|
||||||
|
efrom!(JaySyncFileSurfaceError, ClientError);
|
||||||
|
|
@ -352,7 +352,7 @@ fn destroy(drm: &OwnedFd, handle: SyncobjHandle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_sync_files<'a, I>(sync_files: I) -> Result<Option<SyncFile>, DrmError>
|
pub fn merge_sync_files<'a, I>(sync_files: I) -> Result<Option<SyncFile>, DrmError>
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = &'a SyncFile>,
|
I: IntoIterator<Item = &'a SyncFile>,
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ pub mod usr_jay_render_ctx;
|
||||||
pub mod usr_jay_screencast;
|
pub mod usr_jay_screencast;
|
||||||
pub mod usr_jay_select_toplevel;
|
pub mod usr_jay_select_toplevel;
|
||||||
pub mod usr_jay_select_workspace;
|
pub mod usr_jay_select_workspace;
|
||||||
|
pub mod usr_jay_sync_file_release;
|
||||||
|
pub mod usr_jay_sync_file_surface;
|
||||||
pub mod usr_jay_toplevel;
|
pub mod usr_jay_toplevel;
|
||||||
pub mod usr_jay_workspace;
|
pub mod usr_jay_workspace;
|
||||||
pub mod usr_jay_workspace_watcher;
|
pub mod usr_jay_workspace_watcher;
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,9 @@ use {
|
||||||
usr_jay_screencast::UsrJayScreencast,
|
usr_jay_screencast::UsrJayScreencast,
|
||||||
usr_jay_select_toplevel::UsrJaySelectToplevel,
|
usr_jay_select_toplevel::UsrJaySelectToplevel,
|
||||||
usr_jay_select_workspace::UsrJaySelectWorkspace,
|
usr_jay_select_workspace::UsrJaySelectWorkspace,
|
||||||
|
usr_jay_sync_file_surface::UsrJaySyncFileSurface,
|
||||||
usr_jay_workspace_watcher::UsrJayWorkspaceWatcher, usr_wl_output::UsrWlOutput,
|
usr_jay_workspace_watcher::UsrJayWorkspaceWatcher, usr_wl_output::UsrWlOutput,
|
||||||
usr_wl_seat::UsrWlSeat,
|
usr_wl_seat::UsrWlSeat, usr_wl_surface::UsrWlSurface,
|
||||||
},
|
},
|
||||||
usr_object::UsrObject,
|
usr_object::UsrObject,
|
||||||
},
|
},
|
||||||
|
|
@ -187,6 +188,22 @@ impl UsrJayCompositor {
|
||||||
self.con.add_object(obj.clone());
|
self.con.add_object(obj.clone());
|
||||||
obj
|
obj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
|
pub fn get_sync_file_surface(&self, surface: &UsrWlSurface) -> Rc<UsrJaySyncFileSurface> {
|
||||||
|
let obj = Rc::new(UsrJaySyncFileSurface {
|
||||||
|
id: self.con.id(),
|
||||||
|
con: self.con.clone(),
|
||||||
|
version: self.version,
|
||||||
|
});
|
||||||
|
self.con.request(GetSyncFileSurface {
|
||||||
|
self_id: self.id,
|
||||||
|
id: obj.id,
|
||||||
|
surface: surface.id,
|
||||||
|
});
|
||||||
|
self.con.add_object(obj.clone());
|
||||||
|
obj
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JayCompositorEventHandler for UsrJayCompositor {
|
impl JayCompositorEventHandler for UsrJayCompositor {
|
||||||
|
|
|
||||||
60
src/wl_usr/usr_ifs/usr_jay_sync_file_release.rs
Normal file
60
src/wl_usr/usr_ifs/usr_jay_sync_file_release.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
gfx_api::SyncFile,
|
||||||
|
object::Version,
|
||||||
|
utils::clonecell::CloneCell,
|
||||||
|
wire::{JaySyncFileReleaseId, jay_sync_file_release::*},
|
||||||
|
wl_usr::{UsrCon, usr_object::UsrObject},
|
||||||
|
},
|
||||||
|
std::{convert::Infallible, rc::Rc},
|
||||||
|
uapi::OwnedFd,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct UsrJaySyncFileRelease {
|
||||||
|
pub id: JaySyncFileReleaseId,
|
||||||
|
pub con: Rc<UsrCon>,
|
||||||
|
pub owner: CloneCell<Option<Rc<dyn UsrJaySyncFileReleaseOwner>>>,
|
||||||
|
pub version: Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait UsrJaySyncFileReleaseOwner {
|
||||||
|
fn release(&self, sync_file: Option<SyncFile>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UsrJaySyncFileRelease {
|
||||||
|
fn release(&self, sf: Option<Rc<OwnedFd>>) {
|
||||||
|
if let Some(owner) = self.owner.get() {
|
||||||
|
owner.release(sf.map(SyncFile));
|
||||||
|
}
|
||||||
|
self.con.remove_obj(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JaySyncFileReleaseEventHandler for UsrJaySyncFileRelease {
|
||||||
|
type Error = Infallible;
|
||||||
|
|
||||||
|
fn release_immediate(&self, _ev: ReleaseImmediate, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
|
self.release(None);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn release_async(&self, ev: ReleaseAsync, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
|
self.release(Some(ev.sync_file));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usr_object_base! {
|
||||||
|
self = UsrJaySyncFileRelease = JaySyncFileRelease;
|
||||||
|
version = self.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UsrObject for UsrJaySyncFileRelease {
|
||||||
|
fn destroy(&self) {
|
||||||
|
self.con.request(Destroy { self_id: self.id });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn break_loops(&self) {
|
||||||
|
self.owner.take();
|
||||||
|
}
|
||||||
|
}
|
||||||
66
src/wl_usr/usr_ifs/usr_jay_sync_file_surface.rs
Normal file
66
src/wl_usr/usr_ifs/usr_jay_sync_file_surface.rs
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
gfx_api::SyncFile,
|
||||||
|
object::Version,
|
||||||
|
wire::{JaySyncFileSurfaceId, jay_sync_file_surface::*},
|
||||||
|
wl_usr::{
|
||||||
|
UsrCon, usr_ifs::usr_jay_sync_file_release::UsrJaySyncFileRelease,
|
||||||
|
usr_object::UsrObject,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
std::{convert::Infallible, rc::Rc},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct UsrJaySyncFileSurface {
|
||||||
|
pub id: JaySyncFileSurfaceId,
|
||||||
|
pub con: Rc<UsrCon>,
|
||||||
|
pub version: Version,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UsrJaySyncFileSurface {
|
||||||
|
#[expect(dead_code)]
|
||||||
|
pub fn set_acquire(&self, sf: Option<&SyncFile>) {
|
||||||
|
match sf {
|
||||||
|
None => {
|
||||||
|
self.con.request(SetAcquireImmediate { self_id: self.id });
|
||||||
|
}
|
||||||
|
Some(sf) => {
|
||||||
|
self.con.request(SetAcquireAsync {
|
||||||
|
self_id: self.id,
|
||||||
|
sync_file: sf.0.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
|
pub fn get_release(&self) -> Rc<UsrJaySyncFileRelease> {
|
||||||
|
let obj = Rc::new(UsrJaySyncFileRelease {
|
||||||
|
id: self.con.id(),
|
||||||
|
con: self.con.clone(),
|
||||||
|
owner: Default::default(),
|
||||||
|
version: self.version,
|
||||||
|
});
|
||||||
|
self.con.request(GetRelease {
|
||||||
|
self_id: self.id,
|
||||||
|
release: obj.id,
|
||||||
|
});
|
||||||
|
self.con.add_object(obj.clone());
|
||||||
|
obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JaySyncFileSurfaceEventHandler for UsrJaySyncFileSurface {
|
||||||
|
type Error = Infallible;
|
||||||
|
}
|
||||||
|
|
||||||
|
usr_object_base! {
|
||||||
|
self = UsrJaySyncFileSurface = JaySyncFileSurface;
|
||||||
|
version = self.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UsrObject for UsrJaySyncFileSurface {
|
||||||
|
fn destroy(&self) {
|
||||||
|
self.con.request(Destroy { self_id: self.id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -126,6 +126,11 @@ request get_tagged_acceptor (since = 25) {
|
||||||
tag: str,
|
tag: str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
request get_sync_file_surface (since = 26) {
|
||||||
|
id: id(jay_sync_file_surface),
|
||||||
|
surface: id(wl_surface),
|
||||||
|
}
|
||||||
|
|
||||||
# events
|
# events
|
||||||
|
|
||||||
event client_id {
|
event client_id {
|
||||||
|
|
|
||||||
11
wire/jay_sync_file_release.txt
Normal file
11
wire/jay_sync_file_release.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
request destroy {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
event release_immediate {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
event release_async {
|
||||||
|
sync_file: fd,
|
||||||
|
}
|
||||||
15
wire/jay_sync_file_surface.txt
Normal file
15
wire/jay_sync_file_surface.txt
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
request destroy {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
request set_acquire_immediate {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
request set_acquire_async {
|
||||||
|
sync_file: fd,
|
||||||
|
}
|
||||||
|
|
||||||
|
request get_release {
|
||||||
|
release: id(jay_sync_file_release) (new),
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue