gfx-api: add support for syncobj synchronization
This commit is contained in:
parent
80a69ba7ef
commit
7e6facf4e3
20 changed files with 323 additions and 159 deletions
|
|
@ -9,7 +9,7 @@ use {
|
||||||
drm_feedback::DrmFeedback,
|
drm_feedback::DrmFeedback,
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
format::Format,
|
format::Format,
|
||||||
gfx_api::{GfxApi, GfxFramebuffer, SyncFile},
|
gfx_api::{FdSync, GfxApi, GfxFramebuffer},
|
||||||
ifs::{
|
ifs::{
|
||||||
wl_output::OutputId,
|
wl_output::OutputId,
|
||||||
wl_seat::{
|
wl_seat::{
|
||||||
|
|
@ -186,7 +186,7 @@ pub trait HardwareCursorUpdate {
|
||||||
fn set_enabled(&mut self, enabled: bool);
|
fn set_enabled(&mut self, enabled: bool);
|
||||||
fn get_buffer(&self) -> Rc<dyn GfxFramebuffer>;
|
fn get_buffer(&self) -> Rc<dyn GfxFramebuffer>;
|
||||||
fn set_position(&mut self, x: i32, y: i32);
|
fn set_position(&mut self, x: i32, y: i32);
|
||||||
fn swap_buffer(&mut self, sync_file: Option<SyncFile>);
|
fn swap_buffer(&mut self, sync: Option<FdSync>);
|
||||||
fn size(&self) -> (i32, i32);
|
fn size(&self) -> (i32, i32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ use {
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
AcquireSync, GfxBlendBuffer, GfxError, GfxFormat, GfxFramebuffer, GfxTexture,
|
AcquireSync, FdSync, GfxBlendBuffer, GfxError, GfxFormat, GfxFramebuffer, GfxTexture,
|
||||||
GfxWriteModifier, ReleaseSync, SyncFile, needs_render_usage,
|
GfxWriteModifier, ReleaseSync, needs_render_usage,
|
||||||
},
|
},
|
||||||
rect::{DamageQueue, Rect, Region},
|
rect::{DamageQueue, Rect, Region},
|
||||||
udmabuf::{Udmabuf, UdmabufError},
|
udmabuf::{Udmabuf, UdmabufError},
|
||||||
|
|
@ -120,15 +120,15 @@ pub enum RenderBufferError {
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct RenderBufferCopy {
|
pub struct RenderBufferCopy {
|
||||||
pub render_block: Option<SyncFile>,
|
pub render_block: Option<FdSync>,
|
||||||
pub present_block: Option<SyncFile>,
|
pub present_block: Option<FdSync>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderBufferCopy {
|
impl RenderBufferCopy {
|
||||||
pub fn for_both(sf: Option<SyncFile>) -> Self {
|
pub fn for_both(sync: Option<FdSync>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
render_block: sf.clone(),
|
render_block: sync.clone(),
|
||||||
present_block: sf,
|
present_block: sync,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -138,12 +138,12 @@ impl RenderBuffer {
|
||||||
&self,
|
&self,
|
||||||
cd: &Rc<ColorDescription>,
|
cd: &Rc<ColorDescription>,
|
||||||
region: Option<&Region>,
|
region: Option<&Region>,
|
||||||
sync_file: Option<SyncFile>,
|
sync: Option<FdSync>,
|
||||||
) -> Result<RenderBufferCopy, RenderBufferError> {
|
) -> Result<RenderBufferCopy, RenderBufferError> {
|
||||||
match &self.prime {
|
match &self.prime {
|
||||||
RenderBufferPrime::None => Ok(RenderBufferCopy {
|
RenderBufferPrime::None => Ok(RenderBufferCopy {
|
||||||
render_block: None,
|
render_block: None,
|
||||||
present_block: sync_file,
|
present_block: sync,
|
||||||
}),
|
}),
|
||||||
RenderBufferPrime::Sampling {
|
RenderBufferPrime::Sampling {
|
||||||
dev_render_tex,
|
dev_render_tex,
|
||||||
|
|
@ -157,7 +157,7 @@ impl RenderBuffer {
|
||||||
dev_render_tex,
|
dev_render_tex,
|
||||||
cd,
|
cd,
|
||||||
None,
|
None,
|
||||||
AcquireSync::from_sync_file(sync_file),
|
AcquireSync::from_fd_sync(sync),
|
||||||
ReleaseSync::None,
|
ReleaseSync::None,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
|
@ -175,7 +175,7 @@ impl RenderBuffer {
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let render_block = render_copy
|
let render_block = render_copy
|
||||||
.execute(sync_file.as_ref(), region)
|
.execute(sync.as_ref(), region)
|
||||||
.map_err(RenderBufferError::CopyRenderToUdmabuf)?;
|
.map_err(RenderBufferError::CopyRenderToUdmabuf)?;
|
||||||
let present_block = dev_copy
|
let present_block = dev_copy
|
||||||
.execute(render_block.as_ref(), region)
|
.execute(render_block.as_ref(), region)
|
||||||
|
|
@ -189,7 +189,7 @@ impl RenderBuffer {
|
||||||
| RenderBufferPrime::CopyDirectPush {
|
| RenderBufferPrime::CopyDirectPush {
|
||||||
render_copy: copy, ..
|
render_copy: copy, ..
|
||||||
} => copy
|
} => copy
|
||||||
.execute(sync_file.as_ref(), region)
|
.execute(sync.as_ref(), region)
|
||||||
.map_err(RenderBufferError::CopyRenderToDev)
|
.map_err(RenderBufferError::CopyRenderToDev)
|
||||||
.map(RenderBufferCopy::for_both),
|
.map(RenderBufferCopy::for_both),
|
||||||
}
|
}
|
||||||
|
|
@ -201,8 +201,8 @@ impl RenderBuffer {
|
||||||
self.damage_queue.damage(&[rect]);
|
self.damage_queue.damage(&[rect]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&self, cd: &Rc<ColorDescription>) -> Result<Option<SyncFile>, RenderBufferError> {
|
pub fn clear(&self, cd: &Rc<ColorDescription>) -> Result<Option<FdSync>, RenderBufferError> {
|
||||||
let sync_file = match &self.prime {
|
let sync = match &self.prime {
|
||||||
RenderBufferPrime::None => {
|
RenderBufferPrime::None => {
|
||||||
self.render
|
self.render
|
||||||
.fb
|
.fb
|
||||||
|
|
@ -222,14 +222,14 @@ impl RenderBuffer {
|
||||||
self.copy_to_dev(cd, None, sf)?.present_block
|
self.copy_to_dev(cd, None, sf)?.present_block
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(sync_file)
|
Ok(sync)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_to_new(
|
pub fn copy_to_new(
|
||||||
&self,
|
&self,
|
||||||
new: &Self,
|
new: &Self,
|
||||||
cd: &Rc<ColorDescription>,
|
cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, RenderBufferError> {
|
) -> Result<Option<FdSync>, RenderBufferError> {
|
||||||
let old = self;
|
let old = self;
|
||||||
|
|
||||||
if (old.width, old.height) != (new.width, new.height) {
|
if (old.width, old.height) != (new.width, new.height) {
|
||||||
|
|
|
||||||
|
|
@ -240,13 +240,8 @@ impl MetalConnector {
|
||||||
// current PresentFb if present_fb is None, potentially mutating the fb that is
|
// current PresentFb if present_fb is None, potentially mutating the fb that is
|
||||||
// currently being scanned out, which would render such a wait absurd.
|
// currently being scanned out, which would render such a wait absurd.
|
||||||
self.perform_screencopies(&present_fb, &node, &cd);
|
self.perform_screencopies(&present_fb, &node, &cd);
|
||||||
if let Some(sync_file) = self.cursor_sync_file.take()
|
if let Some(sync) = self.cursor_sync.take() {
|
||||||
&& let Err(e) = self.state.ring.readable(&sync_file).await
|
sync.signaled(&self.state.ring, "cursor").await;
|
||||||
{
|
|
||||||
log::error!(
|
|
||||||
"Could not wait for cursor sync file to complete: {}",
|
|
||||||
ErrorFmt(e)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
self.await_present_fb(present_fb.as_mut(), PresentFbWait::Scanout)
|
self.await_present_fb(present_fb.as_mut(), PresentFbWait::Scanout)
|
||||||
.await;
|
.await;
|
||||||
|
|
@ -353,19 +348,14 @@ impl MetalConnector {
|
||||||
W::Render => &mut fb.copy.render_block,
|
W::Render => &mut fb.copy.render_block,
|
||||||
W::Scanout => &mut fb.copy.present_block,
|
W::Scanout => &mut fb.copy.present_block,
|
||||||
};
|
};
|
||||||
let Some(sync_file) = field.take() else {
|
let Some(sync) = field.take() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if let Err(e) = self.state.ring.readable(&sync_file).await {
|
let name = match wait {
|
||||||
let name = match wait {
|
W::Render => "render",
|
||||||
W::Render => "render",
|
W::Scanout => "scanout",
|
||||||
W::Scanout => "scanout",
|
};
|
||||||
};
|
sync.signaled(&self.state.ring, name).await;
|
||||||
log::error!(
|
|
||||||
"Could not wait for primary {name} sync file to complete: {}",
|
|
||||||
ErrorFmt(e),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_async_flip(&self) -> bool {
|
fn try_async_flip(&self) -> bool {
|
||||||
|
|
@ -554,13 +544,13 @@ impl MetalConnector {
|
||||||
self.state.present_hardware_cursor(node, &mut c);
|
self.state.present_hardware_cursor(node, &mut c);
|
||||||
let swap_buffers = c.cursor_swap_buffer.is_some();
|
let swap_buffers = c.cursor_swap_buffer.is_some();
|
||||||
self.cursor_swap_buffer.set(swap_buffers);
|
self.cursor_swap_buffer.set(swap_buffers);
|
||||||
if let Some(sf) = c.cursor_swap_buffer.take() {
|
if let Some(sync) = c.cursor_swap_buffer.take() {
|
||||||
let sf = c
|
let sync = c
|
||||||
.cursor_buffer
|
.cursor_buffer
|
||||||
.copy_to_dev(cd, None, sf)
|
.copy_to_dev(cd, None, sync)
|
||||||
.map_err(MetalError::CopyToDev)?
|
.map_err(MetalError::CopyToDev)?
|
||||||
.present_block;
|
.present_block;
|
||||||
self.cursor_sync_file.set(sf);
|
self.cursor_sync.set(sync);
|
||||||
}
|
}
|
||||||
let mut cursor_changed = false;
|
let mut cursor_changed = false;
|
||||||
cursor_changed |= self.cursor_enabled.replace(c.cursor_enabled) != c.cursor_enabled;
|
cursor_changed |= self.cursor_enabled.replace(c.cursor_enabled) != c.cursor_enabled;
|
||||||
|
|
@ -886,13 +876,13 @@ impl MetalConnector {
|
||||||
tex = buffer.render.tex.clone();
|
tex = buffer.render.tex.clone();
|
||||||
}
|
}
|
||||||
Some(dsd) => {
|
Some(dsd) => {
|
||||||
let sf = match &dsd.acquire_sync {
|
let sync = match &dsd.acquire_sync {
|
||||||
AcquireSync::None => None,
|
AcquireSync::None => None,
|
||||||
AcquireSync::Implicit => None,
|
AcquireSync::Implicit => None,
|
||||||
AcquireSync::SyncFile { sync_file } => Some(sync_file.clone()),
|
AcquireSync::FdSync(sync) => Some(sync.clone()),
|
||||||
AcquireSync::Unnecessary => None,
|
AcquireSync::Unnecessary => None,
|
||||||
};
|
};
|
||||||
copy = RenderBufferCopy::for_both(sf);
|
copy = RenderBufferCopy::for_both(sync);
|
||||||
fb = dsd.fb.clone();
|
fb = dsd.fb.clone();
|
||||||
tex = dsd.tex.clone();
|
tex = dsd.tex.clone();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,7 @@ impl MetalDeviceTransaction {
|
||||||
let mut unused_crtcs = BinarySearchMap::<_, _, SIZE>::new();
|
let mut unused_crtcs = BinarySearchMap::<_, _, SIZE>::new();
|
||||||
let mut unused_planes = BinarySearchMap::<_, _, SIZE>::new();
|
let mut unused_planes = BinarySearchMap::<_, _, SIZE>::new();
|
||||||
let mut crtc_planes = BinarySearchMap::<_, _, SIZE>::new();
|
let mut crtc_planes = BinarySearchMap::<_, _, SIZE>::new();
|
||||||
let mut sync_files = vec![];
|
let mut syncs = vec![];
|
||||||
let slf = &mut self.common;
|
let slf = &mut self.common;
|
||||||
for (_, crtc) in &mut slf.crtcs {
|
for (_, crtc) in &mut slf.crtcs {
|
||||||
crtc_planes.insert(crtc.obj.id, CrtcPlanes::default());
|
crtc_planes.insert(crtc.obj.id, CrtcPlanes::default());
|
||||||
|
|
@ -615,7 +615,7 @@ impl MetalDeviceTransaction {
|
||||||
new_buffer.clear(&cd)
|
new_buffer.clear(&cd)
|
||||||
};
|
};
|
||||||
match res {
|
match res {
|
||||||
Ok(sf) => sync_files.extend(sf),
|
Ok(sf) => syncs.extend(sf),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("Could not clear new buffer: {}", ErrorFmt(e));
|
log::warn!("Could not clear new buffer: {}", ErrorFmt(e));
|
||||||
}
|
}
|
||||||
|
|
@ -653,7 +653,7 @@ impl MetalDeviceTransaction {
|
||||||
match res {
|
match res {
|
||||||
Ok(sf) => {
|
Ok(sf) => {
|
||||||
buffer.locked.set(true);
|
buffer.locked.set(true);
|
||||||
sync_files.extend(sf);
|
syncs.extend(sf);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!(
|
log::error!(
|
||||||
|
|
@ -753,19 +753,8 @@ impl MetalDeviceTransaction {
|
||||||
plane.new = DrmPlaneState::default();
|
plane.new = DrmPlaneState::default();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for sf in sync_files {
|
for sync in syncs {
|
||||||
let mut pollfd = c::pollfd {
|
sync.signaled_blocking("transaction");
|
||||||
fd: sf.0.raw(),
|
|
||||||
events: c::POLLIN,
|
|
||||||
revents: 0,
|
|
||||||
};
|
|
||||||
let res = uapi::poll(slice::from_mut(&mut pollfd), -1);
|
|
||||||
if let Err(e) = res {
|
|
||||||
log::warn!(
|
|
||||||
"Could not wait for sync file to become readable: {}",
|
|
||||||
ErrorFmt(e)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(MetalDeviceTransactionWithDrmState {
|
Ok(MetalDeviceTransactionWithDrmState {
|
||||||
common: self.common,
|
common: self.common,
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ use {
|
||||||
drm_feedback::DrmFeedback,
|
drm_feedback::DrmFeedback,
|
||||||
edid::{CtaDataBlock, Descriptor, EdidExtension},
|
edid::{CtaDataBlock, Descriptor, EdidExtension},
|
||||||
format::{Format, XRGB8888},
|
format::{Format, XRGB8888},
|
||||||
gfx_api::{GfxApi, GfxContext, GfxFramebuffer, SyncFile},
|
gfx_api::{FdSync, GfxApi, GfxContext, GfxFramebuffer},
|
||||||
ifs::{
|
ifs::{
|
||||||
wl_output::OutputId,
|
wl_output::OutputId,
|
||||||
wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC, KIND_ZERO_COPY},
|
wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC, KIND_ZERO_COPY},
|
||||||
|
|
@ -534,7 +534,7 @@ pub struct MetalConnector {
|
||||||
pub cursor_enabled: Cell<bool>,
|
pub cursor_enabled: Cell<bool>,
|
||||||
pub cursor_buffers: CloneCell<Option<Rc<[RenderBuffer; 2]>>>,
|
pub cursor_buffers: CloneCell<Option<Rc<[RenderBuffer; 2]>>>,
|
||||||
pub cursor_swap_buffer: Cell<bool>,
|
pub cursor_swap_buffer: Cell<bool>,
|
||||||
pub cursor_sync_file: CloneCell<Option<SyncFile>>,
|
pub cursor_sync: CloneCell<Option<FdSync>>,
|
||||||
|
|
||||||
pub drm_feedback: CloneCell<Option<Rc<DrmFeedback>>>,
|
pub drm_feedback: CloneCell<Option<Rc<DrmFeedback>>>,
|
||||||
pub scanout_buffers: RefCell<AHashMap<DmaBufId, DirectScanoutCache>>,
|
pub scanout_buffers: RefCell<AHashMap<DmaBufId, DirectScanoutCache>>,
|
||||||
|
|
@ -565,7 +565,7 @@ pub struct MetalHardwareCursor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MetalHardwareCursorChange<'a> {
|
pub struct MetalHardwareCursorChange<'a> {
|
||||||
pub cursor_swap_buffer: Option<Option<SyncFile>>,
|
pub cursor_swap_buffer: Option<Option<FdSync>>,
|
||||||
pub cursor_enabled: bool,
|
pub cursor_enabled: bool,
|
||||||
pub cursor_x: i32,
|
pub cursor_x: i32,
|
||||||
pub cursor_y: i32,
|
pub cursor_y: i32,
|
||||||
|
|
@ -603,8 +603,8 @@ impl HardwareCursorUpdate for MetalHardwareCursorChange<'_> {
|
||||||
self.cursor_y = y;
|
self.cursor_y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn swap_buffer(&mut self, sync_file: Option<SyncFile>) {
|
fn swap_buffer(&mut self, sync: Option<FdSync>) {
|
||||||
self.cursor_swap_buffer = Some(sync_file);
|
self.cursor_swap_buffer = Some(sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(&self) -> (i32, i32) {
|
fn size(&self) -> (i32, i32) {
|
||||||
|
|
@ -1127,7 +1127,7 @@ fn create_connector(
|
||||||
cursor_changed: Cell::new(false),
|
cursor_changed: Cell::new(false),
|
||||||
cursor_damage: Cell::new(false),
|
cursor_damage: Cell::new(false),
|
||||||
cursor_swap_buffer: Cell::new(false),
|
cursor_swap_buffer: Cell::new(false),
|
||||||
cursor_sync_file: Default::default(),
|
cursor_sync: Default::default(),
|
||||||
drm_feedback: Default::default(),
|
drm_feedback: Default::default(),
|
||||||
scanout_buffers: Default::default(),
|
scanout_buffers: Default::default(),
|
||||||
active_framebuffer: Default::default(),
|
active_framebuffer: Default::default(),
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
async_engine::{AsyncEngine, SpawnedFuture},
|
async_engine::{AsyncEngine, SpawnedFuture},
|
||||||
format::{FORMATS, Format},
|
format::{FORMATS, Format},
|
||||||
gfx_api::SyncFile,
|
gfx_api::{FdSync, SyncFile},
|
||||||
io_uring::IoUring,
|
io_uring::IoUring,
|
||||||
rect::{Rect, Region},
|
rect::{Rect, Region},
|
||||||
utils::{
|
utils::{
|
||||||
|
|
@ -1296,9 +1296,9 @@ impl CopyDeviceCopy {
|
||||||
|
|
||||||
pub fn execute(
|
pub fn execute(
|
||||||
&self,
|
&self,
|
||||||
sync_file: Option<&SyncFile>,
|
sync: Option<&FdSync>,
|
||||||
region: Option<&Region>,
|
region: Option<&Region>,
|
||||||
) -> Result<Option<SyncFile>, CopyDeviceError> {
|
) -> Result<Option<FdSync>, CopyDeviceError> {
|
||||||
self.ensure_not_busy()?;
|
self.ensure_not_busy()?;
|
||||||
let slf = &*self.inner;
|
let slf = &*self.inner;
|
||||||
let tt = slf.tt;
|
let tt = slf.tt;
|
||||||
|
|
@ -1656,7 +1656,9 @@ impl CopyDeviceCopy {
|
||||||
}
|
}
|
||||||
let mut wait_semaphore = None;
|
let mut wait_semaphore = None;
|
||||||
let mut wait_semaphores = ArrayVec::<_, 1>::new();
|
let mut wait_semaphores = ArrayVec::<_, 1>::new();
|
||||||
if let Some(sync_file) = sync_file {
|
if let Some(sync) = sync
|
||||||
|
&& let Some(sync_file) = sync.get_sync_file()
|
||||||
|
{
|
||||||
let semaphore = match slf.dev.semaphores.pop() {
|
let semaphore = match slf.dev.semaphores.pop() {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
_ => slf.dev.create_semaphore()?,
|
_ => slf.dev.create_semaphore()?,
|
||||||
|
|
@ -1703,7 +1705,7 @@ impl CopyDeviceCopy {
|
||||||
fence: Some(signal_fence),
|
fence: Some(signal_fence),
|
||||||
};
|
};
|
||||||
slf.dev.submissions[tt].pending.push(pending);
|
slf.dev.submissions[tt].pending.push(pending);
|
||||||
Ok(sync_file)
|
Ok(sync_file.map(FdSync::SyncFile))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -514,8 +514,8 @@ impl CursorUser {
|
||||||
&cd,
|
&cd,
|
||||||
);
|
);
|
||||||
match res {
|
match res {
|
||||||
Ok(sync_file) => {
|
Ok(sync) => {
|
||||||
hc.swap_buffer(sync_file);
|
hc.swap_buffer(sync);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Could not render hardware cursor: {}", ErrorFmt(e));
|
log::error!("Could not render hardware cursor: {}", ErrorFmt(e));
|
||||||
|
|
|
||||||
|
|
@ -64,12 +64,10 @@ impl EventfdCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eventfd {
|
impl Eventfd {
|
||||||
#[expect(dead_code)]
|
|
||||||
pub fn is_signaled(&self) -> bool {
|
pub fn is_signaled(&self) -> bool {
|
||||||
self.signaled.get()
|
self.signaled.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(not(test), expect(dead_code))]
|
|
||||||
pub async fn signaled(&self) -> Result<(), IoUringError> {
|
pub async fn signaled(&self) -> Result<(), IoUringError> {
|
||||||
if self.signaled.get() {
|
if self.signaled.get() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
@ -79,7 +77,6 @@ impl Eventfd {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[expect(dead_code)]
|
|
||||||
pub fn signaled_blocking(&self) -> Result<(), OsError> {
|
pub fn signaled_blocking(&self) -> Result<(), OsError> {
|
||||||
if self.signaled.get() {
|
if self.signaled.get() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
|
||||||
163
src/gfx_api.rs
163
src/gfx_api.rs
|
|
@ -5,16 +5,22 @@ use {
|
||||||
cpu_worker::CpuWorker,
|
cpu_worker::CpuWorker,
|
||||||
cursor::Cursor,
|
cursor::Cursor,
|
||||||
damage::DamageVisualizer,
|
damage::DamageVisualizer,
|
||||||
|
eventfd_cache::Eventfd,
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
format::Format,
|
format::Format,
|
||||||
|
io_uring::{IoUring, IoUringError},
|
||||||
rect::{Rect, Region},
|
rect::{Rect, Region},
|
||||||
renderer::{Renderer, renderer_base::RendererBase},
|
renderer::{Renderer, renderer_base::RendererBase},
|
||||||
scale::Scale,
|
scale::Scale,
|
||||||
state::State,
|
state::State,
|
||||||
theme::Color,
|
theme::Color,
|
||||||
tree::{Node, OutputNode, Transform},
|
tree::{Node, OutputNode, Transform},
|
||||||
utils::clonecell::UnsafeCellCloneSafe,
|
utils::{clonecell::UnsafeCellCloneSafe, errorfmt::ErrorFmt},
|
||||||
video::{Modifier, dmabuf::DmaBuf, drm::syncobj::SyncobjCtx},
|
video::{
|
||||||
|
Modifier,
|
||||||
|
dmabuf::DmaBuf,
|
||||||
|
drm::syncobj::{Syncobj, SyncobjCtx, SyncobjPoint},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
indexmap::{IndexMap, IndexSet},
|
indexmap::{IndexMap, IndexSet},
|
||||||
|
|
@ -22,16 +28,17 @@ use {
|
||||||
linearize::Linearize,
|
linearize::Linearize,
|
||||||
std::{
|
std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
cell::Cell,
|
cell::{Cell, OnceCell},
|
||||||
error::Error,
|
error::Error,
|
||||||
ffi::CString,
|
ffi::CString,
|
||||||
fmt::{Debug, Formatter},
|
fmt::{Debug, Formatter},
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
slice,
|
||||||
sync::atomic::{AtomicU64, Ordering::Relaxed},
|
sync::atomic::{AtomicU64, Ordering::Relaxed},
|
||||||
},
|
},
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
uapi::OwnedFd,
|
uapi::{OwnedFd, c},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Linearize)]
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Linearize)]
|
||||||
|
|
@ -285,15 +292,24 @@ unsafe impl UnsafeCellCloneSafe for SyncFile {}
|
||||||
pub enum AcquireSync {
|
pub enum AcquireSync {
|
||||||
None,
|
None,
|
||||||
Implicit,
|
Implicit,
|
||||||
SyncFile { sync_file: SyncFile },
|
FdSync(FdSync),
|
||||||
Unnecessary,
|
Unnecessary,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AcquireSync {
|
impl AcquireSync {
|
||||||
pub fn from_sync_file(sync_file: Option<SyncFile>) -> Self {
|
pub fn from_fd_sync(sync: Option<FdSync>) -> Self {
|
||||||
match sync_file {
|
match sync {
|
||||||
None => Self::Unnecessary,
|
None => Self::Unnecessary,
|
||||||
Some(sync_file) => Self::SyncFile { sync_file },
|
Some(sync) => Self::FdSync(sync),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_sync_file(&self) -> Option<&SyncFile> {
|
||||||
|
match self {
|
||||||
|
Self::None => None,
|
||||||
|
Self::Implicit => None,
|
||||||
|
Self::FdSync(sync) => sync.get_sync_file(),
|
||||||
|
Self::Unnecessary => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -310,7 +326,7 @@ impl Debug for AcquireSync {
|
||||||
let name = match self {
|
let name = match self {
|
||||||
AcquireSync::None => "None",
|
AcquireSync::None => "None",
|
||||||
AcquireSync::Implicit => "Implicit",
|
AcquireSync::Implicit => "Implicit",
|
||||||
AcquireSync::SyncFile { .. } => "SyncFile",
|
AcquireSync::FdSync(d) => return Debug::fmt(d, f),
|
||||||
AcquireSync::Unnecessary => "Unnecessary",
|
AcquireSync::Unnecessary => "Unnecessary",
|
||||||
};
|
};
|
||||||
f.debug_struct(name).finish_non_exhaustive()
|
f.debug_struct(name).finish_non_exhaustive()
|
||||||
|
|
@ -318,7 +334,7 @@ impl Debug for AcquireSync {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BufferResv: Debug {
|
pub trait BufferResv: Debug {
|
||||||
fn set_sync_file(&self, user: BufferResvUser, sync_file: &SyncFile);
|
fn set_sync(&self, user: BufferResvUser, sync: &FdSync);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
|
@ -363,7 +379,7 @@ pub trait GfxFramebuffer: Debug {
|
||||||
region: &Region,
|
region: &Region,
|
||||||
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
||||||
blend_cd: &Rc<ColorDescription>,
|
blend_cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, GfxError>;
|
) -> Result<Option<FdSync>, GfxError>;
|
||||||
|
|
||||||
fn format(&self) -> &'static Format;
|
fn format(&self) -> &'static Format;
|
||||||
|
|
||||||
|
|
@ -398,7 +414,7 @@ impl dyn GfxFramebuffer {
|
||||||
clear_cd: &Rc<LinearColorDescription>,
|
clear_cd: &Rc<LinearColorDescription>,
|
||||||
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
||||||
blend_cd: &Rc<ColorDescription>,
|
blend_cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
self.clone().render_with_region(
|
self.clone().render_with_region(
|
||||||
acquire_sync,
|
acquire_sync,
|
||||||
release_sync,
|
release_sync,
|
||||||
|
|
@ -417,7 +433,7 @@ impl dyn GfxFramebuffer {
|
||||||
acquire_sync: AcquireSync,
|
acquire_sync: AcquireSync,
|
||||||
release_sync: ReleaseSync,
|
release_sync: ReleaseSync,
|
||||||
cd: &Rc<ColorDescription>,
|
cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
self.clear_with(
|
self.clear_with(
|
||||||
acquire_sync,
|
acquire_sync,
|
||||||
release_sync,
|
release_sync,
|
||||||
|
|
@ -434,7 +450,7 @@ impl dyn GfxFramebuffer {
|
||||||
cd: &Rc<ColorDescription>,
|
cd: &Rc<ColorDescription>,
|
||||||
color: &Color,
|
color: &Color,
|
||||||
color_cd: &Rc<LinearColorDescription>,
|
color_cd: &Rc<LinearColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
self.render(
|
self.render(
|
||||||
acquire_sync,
|
acquire_sync,
|
||||||
release_sync,
|
release_sync,
|
||||||
|
|
@ -472,7 +488,7 @@ impl dyn GfxFramebuffer {
|
||||||
release_sync: ReleaseSync,
|
release_sync: ReleaseSync,
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
let mut ops = vec![];
|
let mut ops = vec![];
|
||||||
let scale = Scale::from_int(1);
|
let scale = Scale::from_int(1);
|
||||||
let mut renderer = self.renderer_base(&mut ops, scale, Transform::None);
|
let mut renderer = self.renderer_base(&mut ops, scale, Transform::None);
|
||||||
|
|
@ -516,7 +532,7 @@ impl dyn GfxFramebuffer {
|
||||||
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
||||||
blend_cd: &Rc<ColorDescription>,
|
blend_cd: &Rc<ColorDescription>,
|
||||||
f: &mut dyn FnMut(&mut RendererBase),
|
f: &mut dyn FnMut(&mut RendererBase),
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
let mut ops = vec![];
|
let mut ops = vec![];
|
||||||
let mut renderer = self.renderer_base(&mut ops, scale, Transform::None);
|
let mut renderer = self.renderer_base(&mut ops, scale, Transform::None);
|
||||||
f(&mut renderer);
|
f(&mut renderer);
|
||||||
|
|
@ -569,7 +585,7 @@ impl dyn GfxFramebuffer {
|
||||||
region: &Region,
|
region: &Region,
|
||||||
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
||||||
blend_cd: &Rc<ColorDescription>,
|
blend_cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
self.clone().render_with_region(
|
self.clone().render_with_region(
|
||||||
acquire_sync,
|
acquire_sync,
|
||||||
release_sync,
|
release_sync,
|
||||||
|
|
@ -596,7 +612,7 @@ impl dyn GfxFramebuffer {
|
||||||
fill_black_in_grace_period: bool,
|
fill_black_in_grace_period: bool,
|
||||||
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
||||||
blend_cd: &Rc<ColorDescription>,
|
blend_cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
self.render_node(
|
self.render_node(
|
||||||
acquire_sync,
|
acquire_sync,
|
||||||
release_sync,
|
release_sync,
|
||||||
|
|
@ -631,7 +647,7 @@ impl dyn GfxFramebuffer {
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
||||||
blend_cd: &Rc<ColorDescription>,
|
blend_cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
let pass = self.create_render_pass(
|
let pass = self.create_render_pass(
|
||||||
node,
|
node,
|
||||||
state,
|
state,
|
||||||
|
|
@ -664,7 +680,7 @@ impl dyn GfxFramebuffer {
|
||||||
scale: Scale,
|
scale: Scale,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
cd: &Rc<ColorDescription>,
|
cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
let mut ops = vec![];
|
let mut ops = vec![];
|
||||||
let mut renderer = Renderer {
|
let mut renderer = Renderer {
|
||||||
base: self.renderer_base(&mut ops, scale, transform),
|
base: self.renderer_base(&mut ops, scale, transform),
|
||||||
|
|
@ -1087,3 +1103,110 @@ pub fn renderer_base<'a>(
|
||||||
pub fn logical_size(physical_size: (i32, i32), transform: Transform) -> (i32, i32) {
|
pub fn logical_size(physical_size: (i32, i32), transform: Transform) -> (i32, i32) {
|
||||||
transform.maybe_swap(physical_size)
|
transform.maybe_swap(physical_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ReservedSyncobjPoint {
|
||||||
|
pub ctx: Rc<SyncobjCtx>,
|
||||||
|
pub syncobj: Rc<Syncobj>,
|
||||||
|
pub point: SyncobjPoint,
|
||||||
|
pub sync_file: OnceCell<Option<SyncFile>>,
|
||||||
|
pub signaled: Eventfd,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ReservedSyncobjPoint {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("ReservedSyncobjPoint")
|
||||||
|
.field("syncobj", &self.syncobj.id())
|
||||||
|
.field("point", &self.point)
|
||||||
|
.finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum FdSync {
|
||||||
|
SyncFile(SyncFile),
|
||||||
|
#[expect(dead_code)]
|
||||||
|
Syncobj(Rc<ReservedSyncobjPoint>),
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl UnsafeCellCloneSafe for FdSync {}
|
||||||
|
|
||||||
|
impl FdSync {
|
||||||
|
pub async fn try_signaled(&self, ring: &Rc<IoUring>) -> Result<(), IoUringError> {
|
||||||
|
match self {
|
||||||
|
FdSync::SyncFile(f) => ring.readable(&f.0).await.map(drop),
|
||||||
|
FdSync::Syncobj(obj) => obj.signaled.signaled().await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn signaled(&self, ring: &Rc<IoUring>, name: &str) {
|
||||||
|
if let Err(e) = self.try_signaled(ring).await {
|
||||||
|
log::error!(
|
||||||
|
"Could not wait for {name} sync to become signaled: {}",
|
||||||
|
ErrorFmt(e),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn signaled_blocking(&self, name: &str) {
|
||||||
|
let res = match self {
|
||||||
|
FdSync::Syncobj(obj) => obj.signaled.signaled_blocking(),
|
||||||
|
FdSync::SyncFile(f) => {
|
||||||
|
let mut pollfd = c::pollfd {
|
||||||
|
fd: f.raw(),
|
||||||
|
events: c::POLLIN,
|
||||||
|
revents: 0,
|
||||||
|
};
|
||||||
|
uapi::poll(slice::from_mut(&mut pollfd), -1)
|
||||||
|
.map(drop)
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Err(e) = res {
|
||||||
|
log::error!(
|
||||||
|
"Could not wait for {name} sync to become signaled: {}",
|
||||||
|
ErrorFmt(e),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
|
pub fn is_unsignaled(&self) -> bool {
|
||||||
|
!self.is_signaled()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_signaled(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
FdSync::Syncobj(obj) => obj.signaled.is_signaled(),
|
||||||
|
FdSync::SyncFile(f) => {
|
||||||
|
let mut pollfd = c::pollfd {
|
||||||
|
fd: f.raw(),
|
||||||
|
events: c::POLLIN,
|
||||||
|
revents: 0,
|
||||||
|
};
|
||||||
|
uapi::poll(slice::from_mut(&mut pollfd), 0) == Ok(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_sync_file(&self) -> Option<&SyncFile> {
|
||||||
|
match self {
|
||||||
|
FdSync::SyncFile(f) => Some(f),
|
||||||
|
FdSync::Syncobj(obj) => {
|
||||||
|
if obj.signaled.is_signaled() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
obj.sync_file
|
||||||
|
.get_or_init(|| {
|
||||||
|
match obj.ctx.export_sync_file_blocking(&obj.syncobj, obj.point) {
|
||||||
|
Ok(sf) => Some(sf),
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Could not export sync file: {}", ErrorFmt(e));
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,8 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
cmm::cmm_eotf::Eotf,
|
cmm::cmm_eotf::Eotf,
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
AcquireSync, CopyTexture, FramebufferRect, GfxApiOpt, GfxContext, GfxError, GfxTexture,
|
AcquireSync, CopyTexture, FdSync, FramebufferRect, GfxApiOpt, GfxContext, GfxError,
|
||||||
ReleaseSync, SyncFile,
|
GfxTexture, ReleaseSync, SyncFile,
|
||||||
},
|
},
|
||||||
gfx_apis::gl::{
|
gfx_apis::gl::{
|
||||||
egl::image::EglImage,
|
egl::image::EglImage,
|
||||||
|
|
@ -221,7 +221,7 @@ struct GlFillRect {
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) -> Option<SyncFile> {
|
fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) -> Option<FdSync> {
|
||||||
let mut state = fb.ctx.gl_state.borrow_mut();
|
let mut state = fb.ctx.gl_state.borrow_mut();
|
||||||
let state = &mut *state;
|
let state = &mut *state;
|
||||||
let mut fill_rect = state.fill_rect.take();
|
let mut fill_rect = state.fill_rect.take();
|
||||||
|
|
@ -301,13 +301,14 @@ fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) -> Option<SyncFile> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let file = FdSync::SyncFile(file);
|
||||||
let user = fb.ctx.buffer_resv_user;
|
let user = fb.ctx.buffer_resv_user;
|
||||||
for op in ops {
|
for op in ops {
|
||||||
if let GfxApiOpt::CopyTexture(ct) = op
|
if let GfxApiOpt::CopyTexture(ct) = op
|
||||||
&& ct.release_sync == ReleaseSync::Explicit
|
&& ct.release_sync == ReleaseSync::Explicit
|
||||||
&& let Some(resv) = &ct.buffer_resv
|
&& let Some(resv) = &ct.buffer_resv
|
||||||
{
|
{
|
||||||
resv.set_sync_file(user, &file);
|
resv.set_sync(user, &file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Some(file);
|
return Some(file);
|
||||||
|
|
@ -417,9 +418,8 @@ fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_explicit_sync(ctx: &GlRenderContext, img: Option<&Rc<EglImage>>, sync: &AcquireSync) {
|
fn handle_explicit_sync(ctx: &GlRenderContext, img: Option<&Rc<EglImage>>, sync: &AcquireSync) {
|
||||||
let sync_file = match sync {
|
let Some(sync_file) = sync.get_sync_file() else {
|
||||||
AcquireSync::None | AcquireSync::Implicit | AcquireSync::Unnecessary => return,
|
return;
|
||||||
AcquireSync::SyncFile { sync_file } => sync_file,
|
|
||||||
};
|
};
|
||||||
let sync_file = match uapi::fcntl_dupfd_cloexec(sync_file.raw(), 0) {
|
let sync_file = match uapi::fcntl_dupfd_cloexec(sync_file.raw(), 0) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ use {
|
||||||
},
|
},
|
||||||
format::Format,
|
format::Format,
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
AcquireSync, AsyncShmGfxTextureCallback, GfxApiOpt, GfxBlendBuffer, GfxError,
|
AcquireSync, AsyncShmGfxTextureCallback, FdSync, GfxApiOpt, GfxBlendBuffer, GfxError,
|
||||||
GfxFramebuffer, GfxInternalFramebuffer, GfxStagingBuffer, PendingShmTransfer,
|
GfxFramebuffer, GfxInternalFramebuffer, GfxStagingBuffer, PendingShmTransfer,
|
||||||
ReleaseSync, ShmMemory, SyncFile,
|
ReleaseSync, ShmMemory,
|
||||||
},
|
},
|
||||||
gfx_apis::gl::{
|
gfx_apis::gl::{
|
||||||
RenderError,
|
RenderError,
|
||||||
|
|
@ -74,7 +74,7 @@ impl Framebuffer {
|
||||||
acquire_sync: AcquireSync,
|
acquire_sync: AcquireSync,
|
||||||
ops: &[GfxApiOpt],
|
ops: &[GfxApiOpt],
|
||||||
clear: Option<&Color>,
|
clear: Option<&Color>,
|
||||||
) -> Result<Option<SyncFile>, RenderError> {
|
) -> Result<Option<FdSync>, RenderError> {
|
||||||
let gles = self.ctx.ctx.dpy.gles;
|
let gles = self.ctx.ctx.dpy.gles;
|
||||||
self.ctx.ctx.with_current(|| {
|
self.ctx.ctx.with_current(|| {
|
||||||
handle_explicit_sync(&self.ctx, self.gl.rb._img.as_ref(), &acquire_sync);
|
handle_explicit_sync(&self.ctx, self.gl.rb._img.as_ref(), &acquire_sync);
|
||||||
|
|
@ -88,13 +88,13 @@ impl Framebuffer {
|
||||||
}
|
}
|
||||||
(gles.glBlendFunc)(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
(gles.glBlendFunc)(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
let fd = run_ops(self, ops);
|
let sync = run_ops(self, ops);
|
||||||
if fd.is_none() {
|
if sync.is_none() {
|
||||||
unsafe {
|
unsafe {
|
||||||
(gles.glFinish)();
|
(gles.glFinish)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(fd)
|
Ok(sync)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +115,7 @@ impl GfxFramebuffer for Framebuffer {
|
||||||
_region: &Region,
|
_region: &Region,
|
||||||
_blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
_blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
||||||
_blend_cd: &Rc<ColorDescription>,
|
_blend_cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
(*self)
|
(*self)
|
||||||
.render(acquire_sync, ops, clear)
|
.render(acquire_sync, ops, clear)
|
||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ use {
|
||||||
format::Format,
|
format::Format,
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback,
|
AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback,
|
||||||
AsyncShmGfxTextureTransferCancellable, GfxApiOpt, GfxBlendBuffer, GfxBuffer, GfxError,
|
AsyncShmGfxTextureTransferCancellable, FdSync, GfxApiOpt, GfxBlendBuffer, GfxBuffer,
|
||||||
GfxFramebuffer, GfxImage, GfxInternalFramebuffer, GfxStagingBuffer, GfxTexture,
|
GfxError, GfxFramebuffer, GfxImage, GfxInternalFramebuffer, GfxStagingBuffer,
|
||||||
PendingShmTransfer, ReleaseSync, ShmGfxTexture, ShmMemory, SyncFile,
|
GfxTexture, PendingShmTransfer, ReleaseSync, ShmGfxTexture, ShmMemory,
|
||||||
},
|
},
|
||||||
gfx_apis::vulkan::{
|
gfx_apis::vulkan::{
|
||||||
VulkanError, allocator::VulkanAllocation, device::VulkanDevice,
|
VulkanError, allocator::VulkanAllocation, device::VulkanDevice,
|
||||||
|
|
@ -563,7 +563,7 @@ impl GfxFramebuffer for VulkanImage {
|
||||||
region: &Region,
|
region: &Region,
|
||||||
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
||||||
blend_cd: &Rc<ColorDescription>,
|
blend_cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
let mut blend_buffer = blend_buffer
|
let mut blend_buffer = blend_buffer
|
||||||
.map(|b| b.clone().into_vk(&self.renderer.device.device))
|
.map(|b| b.clone().into_vk(&self.renderer.device.device))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use {
|
||||||
},
|
},
|
||||||
cpu_worker::PendingJob,
|
cpu_worker::PendingJob,
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
AcquireSync, AlphaMode, BufferResv, BufferResvUser, GfxApiOpt, GfxBlendBuffer,
|
AcquireSync, AlphaMode, BufferResv, BufferResvUser, FdSync, GfxApiOpt, GfxBlendBuffer,
|
||||||
GfxFormat, GfxTexture, GfxWriteModifier, ReleaseSync, SyncFile,
|
GfxFormat, GfxTexture, GfxWriteModifier, ReleaseSync, SyncFile,
|
||||||
},
|
},
|
||||||
gfx_apis::vulkan::{
|
gfx_apis::vulkan::{
|
||||||
|
|
@ -1671,10 +1671,12 @@ impl VulkanRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AcquireSync::SyncFile { sync_file } => {
|
AcquireSync::FdSync(sync) => {
|
||||||
let fd = uapi::fcntl_dupfd_cloexec(sync_file.raw(), 0)
|
if let Some(sync_file) = sync.get_sync_file() {
|
||||||
.map_err(|e| VulkanError::Dupfd(e.into()))?;
|
let fd = uapi::fcntl_dupfd_cloexec(sync_file.raw(), 0)
|
||||||
import_sync_file(fd)?;
|
.map_err(|e| VulkanError::Dupfd(e.into()))?;
|
||||||
|
import_sync_file(fd)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AcquireSync::Unnecessary => {}
|
AcquireSync::Unnecessary => {}
|
||||||
}
|
}
|
||||||
|
|
@ -1707,13 +1709,14 @@ impl VulkanRenderer {
|
||||||
Some(sync_file) => sync_file,
|
Some(sync_file) => sync_file,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
let fd_sync = FdSync::SyncFile(sync_file.clone());
|
||||||
let import =
|
let import =
|
||||||
|img: &VulkanImage, sync: ReleaseSync, resv: Option<Rc<dyn BufferResv>>, flag: u32| {
|
|img: &VulkanImage, sync: ReleaseSync, resv: Option<Rc<dyn BufferResv>>, flag: u32| {
|
||||||
if sync == ReleaseSync::None {
|
if sync == ReleaseSync::None {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(resv) = resv {
|
if let Some(resv) = resv {
|
||||||
resv.set_sync_file(self.buffer_resv_user, sync_file);
|
resv.set_sync(self.buffer_resv_user, &fd_sync);
|
||||||
} else if sync == ReleaseSync::Implicit {
|
} else if sync == ReleaseSync::Implicit {
|
||||||
if let VulkanImageMemory::DmaBuf(buf) = &img.ty
|
if let VulkanImageMemory::DmaBuf(buf) = &img.ty
|
||||||
&& let Err(e) = buf.template.dmabuf.import_sync_file(flag, sync_file)
|
&& let Err(e) = buf.template.dmabuf.import_sync_file(flag, sync_file)
|
||||||
|
|
@ -1844,7 +1847,7 @@ impl VulkanRenderer {
|
||||||
region: &Region,
|
region: &Region,
|
||||||
blend_buffer: Option<Rc<VulkanImage>>,
|
blend_buffer: Option<Rc<VulkanImage>>,
|
||||||
blend_cd: &Rc<ColorDescription>,
|
blend_cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, VulkanError> {
|
) -> Result<Option<FdSync>, VulkanError> {
|
||||||
zone!("execute");
|
zone!("execute");
|
||||||
let res = self.try_execute(
|
let res = self.try_execute(
|
||||||
fb,
|
fb,
|
||||||
|
|
@ -1870,7 +1873,7 @@ impl VulkanRenderer {
|
||||||
memory.ops_tmp.clear();
|
memory.ops_tmp.clear();
|
||||||
memory.release_sync_file.take()
|
memory.release_sync_file.take()
|
||||||
};
|
};
|
||||||
res.map(|_| sync_file)
|
res.map(|_| sync_file.map(FdSync::SyncFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocate_semaphore(&self) -> Result<Rc<VulkanSemaphore>, VulkanError> {
|
fn allocate_semaphore(&self) -> Result<Rc<VulkanSemaphore>, VulkanError> {
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ use {
|
||||||
client::{Client, ClientError},
|
client::{Client, ClientError},
|
||||||
cmm::cmm_description::ColorDescription,
|
cmm::cmm_description::ColorDescription,
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
AcquireSync, AsyncShmGfxTextureCallback, BufferResv, GfxError, GfxFramebuffer,
|
AcquireSync, AsyncShmGfxTextureCallback, BufferResv, FdSync, GfxError, GfxFramebuffer,
|
||||||
GfxTexture, ReleaseSync, STAGING_DOWNLOAD, SyncFile,
|
GfxTexture, ReleaseSync, STAGING_DOWNLOAD,
|
||||||
},
|
},
|
||||||
ifs::{
|
ifs::{
|
||||||
ext_image_capture_source_v1::ImageCaptureSource,
|
ext_image_capture_source_v1::ImageCaptureSource,
|
||||||
|
|
@ -78,7 +78,7 @@ impl ExtImageCopyCaptureFrameV1 {
|
||||||
Rc<dyn GfxFramebuffer>,
|
Rc<dyn GfxFramebuffer>,
|
||||||
AcquireSync,
|
AcquireSync,
|
||||||
ReleaseSync,
|
ReleaseSync,
|
||||||
) -> Result<Option<SyncFile>, GfxError>,
|
) -> Result<Option<FdSync>, GfxError>,
|
||||||
) -> Result<(), FrameFailureReason> {
|
) -> Result<(), FrameFailureReason> {
|
||||||
let Some(ctx) = self.client.state.render_ctx.get() else {
|
let Some(ctx) = self.client.state.render_ctx.get() else {
|
||||||
return Err(FrameFailureReason::BufferConstraints);
|
return Err(FrameFailureReason::BufferConstraints);
|
||||||
|
|
@ -183,7 +183,7 @@ impl ExtImageCopyCaptureFrameV1 {
|
||||||
Rc<dyn GfxFramebuffer>,
|
Rc<dyn GfxFramebuffer>,
|
||||||
AcquireSync,
|
AcquireSync,
|
||||||
ReleaseSync,
|
ReleaseSync,
|
||||||
) -> Result<Option<SyncFile>, GfxError>,
|
) -> Result<Option<FdSync>, GfxError>,
|
||||||
) {
|
) {
|
||||||
match self.try_copy(on, size, f) {
|
match self.try_copy(on, size, f) {
|
||||||
Ok(()) => self.session.status.set(FrameStatus::Captured),
|
Ok(()) => self.session.status.set(FrameStatus::Captured),
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ use {
|
||||||
drm_feedback::DrmFeedback,
|
drm_feedback::DrmFeedback,
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
AlphaMode, AsyncShmGfxTexture, BufferResv, BufferResvUser, GfxError, GfxStagingBuffer,
|
AlphaMode, AsyncShmGfxTexture, BufferResv, BufferResvUser, FdSync, GfxError,
|
||||||
ReleaseSync, SampleRect, SyncFile,
|
GfxStagingBuffer, ReleaseSync, SampleRect,
|
||||||
},
|
},
|
||||||
ifs::{
|
ifs::{
|
||||||
color_management::wp_color_management_surface_feedback_v1::WpColorManagementSurfaceFeedbackV1,
|
color_management::wp_color_management_surface_feedback_v1::WpColorManagementSurfaceFeedbackV1,
|
||||||
|
|
@ -215,7 +215,7 @@ impl NodeVisitorBase for SurfaceSendPreferredColorDescription {
|
||||||
|
|
||||||
pub struct SurfaceBuffer {
|
pub struct SurfaceBuffer {
|
||||||
pub buffer: AttachedBuffer,
|
pub buffer: AttachedBuffer,
|
||||||
sync_files: SmallMap<BufferResvUser, SyncFile, 1>,
|
syncs: SmallMap<BufferResvUser, FdSync, 1>,
|
||||||
pub release_sync: ReleaseSync,
|
pub release_sync: ReleaseSync,
|
||||||
release: Option<SyncobjRelease>,
|
release: Option<SyncobjRelease>,
|
||||||
_surface_release: SmallVec<[SurfaceRelease; 1]>,
|
_surface_release: SmallVec<[SurfaceRelease; 1]>,
|
||||||
|
|
@ -223,14 +223,16 @@ pub struct SurfaceBuffer {
|
||||||
|
|
||||||
impl Drop for SurfaceBuffer {
|
impl Drop for SurfaceBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let sync_files = self.sync_files.take();
|
let syncs = self.syncs.take();
|
||||||
if let Some(release) = &mut self.release {
|
if let Some(release) = &mut self.release {
|
||||||
release.signal(Some(&sync_files));
|
release.signal(Some(&syncs));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(dmabuf) = &self.buffer.buf.client_dmabuf {
|
if let Some(dmabuf) = &self.buffer.buf.client_dmabuf {
|
||||||
for (_, sync_file) in &sync_files {
|
for (_, sync) in &syncs {
|
||||||
if let Err(e) = dmabuf.import_sync_file(DMA_BUF_SYNC_READ, sync_file) {
|
if let Some(sf) = sync.get_sync_file()
|
||||||
|
&& let Err(e) = dmabuf.import_sync_file(DMA_BUF_SYNC_READ, &sf)
|
||||||
|
{
|
||||||
log::error!("Could not import sync file: {}", ErrorFmt(e));
|
log::error!("Could not import sync file: {}", ErrorFmt(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -245,8 +247,8 @@ impl Debug for SurfaceBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BufferResv for SurfaceBuffer {
|
impl BufferResv for SurfaceBuffer {
|
||||||
fn set_sync_file(&self, user: BufferResvUser, sync_file: &SyncFile) {
|
fn set_sync(&self, user: BufferResvUser, sync: &FdSync) {
|
||||||
self.sync_files.insert(user, sync_file.clone());
|
self.syncs.insert(user, sync.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1231,7 +1233,7 @@ impl WlSurface {
|
||||||
};
|
};
|
||||||
let surface_buffer = SurfaceBuffer {
|
let surface_buffer = SurfaceBuffer {
|
||||||
buffer,
|
buffer,
|
||||||
sync_files: 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),
|
||||||
|
|
@ -2263,7 +2265,7 @@ pub struct SyncobjRelease {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SyncobjRelease {
|
impl SyncobjRelease {
|
||||||
fn signal(&mut self, sync_files: Option<&SmallVec<[(BufferResvUser, SyncFile); 1]>>) {
|
fn signal(&mut self, syncs: Option<&SmallVec<[(BufferResvUser, FdSync); 1]>>) {
|
||||||
if !self.committed {
|
if !self.committed {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2278,10 +2280,14 @@ impl SyncobjRelease {
|
||||||
log::error!("Cannot signal release point because there is no syncobj context");
|
log::error!("Cannot signal release point because there is no syncobj context");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if let Some(sync_files) = sync_files
|
if let Some(syncs) = syncs
|
||||||
&& sync_files.is_not_empty()
|
&& syncs.is_not_empty()
|
||||||
{
|
{
|
||||||
let res = ctx.import_sync_files(&syncobj, self.point, sync_files.iter().map(|f| &f.1));
|
let res = ctx.import_sync_files(
|
||||||
|
&syncobj,
|
||||||
|
self.point,
|
||||||
|
syncs.iter().flat_map(|f| f.1.get_sync_file()),
|
||||||
|
);
|
||||||
match res {
|
match res {
|
||||||
Ok(_) => return,
|
Ok(_) => return,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ use {
|
||||||
cpu_worker::CpuWorker,
|
cpu_worker::CpuWorker,
|
||||||
format::{ARGB8888, Format, XRGB8888},
|
format::{ARGB8888, Format, XRGB8888},
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback, CopyTexture, FillRect,
|
AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback, CopyTexture, FdSync,
|
||||||
FramebufferRect, GfxApi, GfxApiOpt, GfxBlendBuffer, GfxContext, GfxError, GfxFormat,
|
FillRect, FramebufferRect, GfxApi, GfxApiOpt, GfxBlendBuffer, GfxContext, GfxError,
|
||||||
GfxFramebuffer, GfxImage, GfxInternalFramebuffer, GfxStagingBuffer, GfxTexture,
|
GfxFormat, GfxFramebuffer, GfxImage, GfxInternalFramebuffer, GfxStagingBuffer,
|
||||||
GfxWriteModifier, PendingShmTransfer, ReleaseSync, ResetStatus, ShmGfxTexture,
|
GfxTexture, GfxWriteModifier, PendingShmTransfer, ReleaseSync, ResetStatus,
|
||||||
ShmMemory, SyncFile,
|
ShmGfxTexture, ShmMemory,
|
||||||
},
|
},
|
||||||
rect::{Rect, Region},
|
rect::{Rect, Region},
|
||||||
theme::Color,
|
theme::Color,
|
||||||
|
|
@ -387,7 +387,7 @@ impl GfxFramebuffer for TestGfxFb {
|
||||||
_region: &Region,
|
_region: &Region,
|
||||||
_blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
_blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
||||||
_blend_cd: &Rc<ColorDescription>,
|
_blend_cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
let fb_points = |width: i32, height: i32, rect: &FramebufferRect| {
|
let fb_points = |width: i32, height: i32, rect: &FramebufferRect| {
|
||||||
let points = rect.to_points();
|
let points = rect.to_points();
|
||||||
let x1 = points[1][0];
|
let x1 = points[1][0];
|
||||||
|
|
|
||||||
14
src/state.rs
14
src/state.rs
|
|
@ -32,9 +32,9 @@ use {
|
||||||
forker::ForkerProxy,
|
forker::ForkerProxy,
|
||||||
format::Format,
|
format::Format,
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
AcquireSync, AlphaMode, BufferResv, GfxApi, GfxBlendBuffer, GfxContext, GfxError,
|
AcquireSync, AlphaMode, BufferResv, FdSync, GfxApi, GfxBlendBuffer, GfxContext,
|
||||||
GfxFramebuffer, GfxTexture, PendingShmTransfer, ReleaseSync, STAGING_DOWNLOAD,
|
GfxError, GfxFramebuffer, GfxTexture, PendingShmTransfer, ReleaseSync,
|
||||||
SampleRect, SyncFile,
|
STAGING_DOWNLOAD, SampleRect,
|
||||||
},
|
},
|
||||||
gfx_apis::create_gfx_context,
|
gfx_apis::create_gfx_context,
|
||||||
globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal},
|
globals::{Globals, GlobalsError, RemovableWaylandGlobal, WaylandGlobal},
|
||||||
|
|
@ -1190,8 +1190,8 @@ impl State {
|
||||||
render_hw_cursor: bool,
|
render_hw_cursor: bool,
|
||||||
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
blend_buffer: Option<&Rc<dyn GfxBlendBuffer>>,
|
||||||
blend_cd: &Rc<ColorDescription>,
|
blend_cd: &Rc<ColorDescription>,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
let sync_file = fb.render_output(
|
let sync = fb.render_output(
|
||||||
acquire_sync,
|
acquire_sync,
|
||||||
release_sync,
|
release_sync,
|
||||||
cd,
|
cd,
|
||||||
|
|
@ -1216,7 +1216,7 @@ impl State {
|
||||||
0,
|
0,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
Ok(sync_file)
|
Ok(sync)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn perform_screencopy(
|
pub fn perform_screencopy(
|
||||||
|
|
@ -1238,7 +1238,7 @@ impl State {
|
||||||
size: Option<(i32, i32)>,
|
size: Option<(i32, i32)>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
scale: Scale,
|
scale: Scale,
|
||||||
) -> Result<Option<SyncFile>, GfxError> {
|
) -> Result<Option<FdSync>, GfxError> {
|
||||||
let mut ops = vec![];
|
let mut ops = vec![];
|
||||||
let mut renderer = Renderer {
|
let mut renderer = Renderer {
|
||||||
base: target.renderer_base(&mut ops, scale, target_transform),
|
base: target.renderer_base(&mut ops, scale, target_transform),
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,8 @@ pub enum DrmError {
|
||||||
Merge(#[source] OsError),
|
Merge(#[source] OsError),
|
||||||
#[error("Could not import a sync file into a syncobj")]
|
#[error("Could not import a sync file into a syncobj")]
|
||||||
ImportSyncFile(#[source] OsError),
|
ImportSyncFile(#[source] OsError),
|
||||||
|
#[error("Could not export a sync file")]
|
||||||
|
ExportSyncFile(#[source] OsError),
|
||||||
#[error("Could not create a lease")]
|
#[error("Could not create a lease")]
|
||||||
CreateLease(#[source] OsError),
|
CreateLease(#[source] OsError),
|
||||||
#[error("Could not drop DRM master")]
|
#[error("Could not drop DRM master")]
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ use {
|
||||||
DRM_SYNCOBJ_CREATE_SIGNALED, DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE,
|
DRM_SYNCOBJ_CREATE_SIGNALED, DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE,
|
||||||
DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE,
|
DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE,
|
||||||
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE,
|
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE,
|
||||||
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE, sync_ioc_merge, syncobj_create,
|
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE,
|
||||||
|
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, sync_ioc_merge, syncobj_create,
|
||||||
syncobj_destroy, syncobj_eventfd, syncobj_fd_to_handle, syncobj_handle_to_fd,
|
syncobj_destroy, syncobj_eventfd, syncobj_fd_to_handle, syncobj_handle_to_fd,
|
||||||
syncobj_signal, syncobj_transfer,
|
syncobj_signal, syncobj_transfer,
|
||||||
},
|
},
|
||||||
|
|
@ -61,6 +62,10 @@ impl Syncobj {
|
||||||
pub fn fd(&self) -> &Rc<OwnedFd> {
|
pub fn fd(&self) -> &Rc<OwnedFd> {
|
||||||
&self.fd
|
&self.fd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn id(&self) -> SyncobjId {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Syncobj {
|
impl Drop for Syncobj {
|
||||||
|
|
@ -118,7 +123,7 @@ impl SyncobjCtx {
|
||||||
pub fn create_syncobj(&self) -> Result<Syncobj, DrmError> {
|
pub fn create_syncobj(&self) -> Result<Syncobj, DrmError> {
|
||||||
let handle = syncobj_create(self.inner.drm.raw(), 0).map_err(DrmError::CreateSyncobj)?;
|
let handle = syncobj_create(self.inner.drm.raw(), 0).map_err(DrmError::CreateSyncobj)?;
|
||||||
let handle = SyncobjHandle(handle);
|
let handle = SyncobjHandle(handle);
|
||||||
let fd = syncobj_handle_to_fd(self.inner.drm.raw(), handle.0, 0);
|
let fd = syncobj_handle_to_fd(self.inner.drm.raw(), handle.0, 0, 0);
|
||||||
if fd.is_err() {
|
if fd.is_err() {
|
||||||
destroy(&self.inner.drm, handle);
|
destroy(&self.inner.drm, handle);
|
||||||
}
|
}
|
||||||
|
|
@ -138,6 +143,7 @@ impl SyncobjCtx {
|
||||||
self.inner.drm.raw(),
|
self.inner.drm.raw(),
|
||||||
handle.0,
|
handle.0,
|
||||||
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE,
|
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE,
|
||||||
|
0,
|
||||||
);
|
);
|
||||||
destroy(&self.inner.drm, handle);
|
destroy(&self.inner.drm, handle);
|
||||||
fd.map_err(DrmError::ExportSyncobj)
|
fd.map_err(DrmError::ExportSyncobj)
|
||||||
|
|
@ -250,7 +256,46 @@ impl SyncobjCtx {
|
||||||
}
|
}
|
||||||
let dummy = self.get_dummy()?;
|
let dummy = self.get_dummy()?;
|
||||||
import(0, self.get_handle(&dummy)?)?;
|
import(0, self.get_handle(&dummy)?)?;
|
||||||
self.transfer(&dummy, SyncobjPoint(0), syncobj, point)
|
self.transfer(&dummy, SyncobjPoint(0), syncobj, point, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn export_sync_file_blocking(
|
||||||
|
&self,
|
||||||
|
syncobj: &Syncobj,
|
||||||
|
point: SyncobjPoint,
|
||||||
|
) -> Result<SyncFile, DrmError> {
|
||||||
|
let export = |flags: u32, handle: SyncobjHandle, point: SyncobjPoint| {
|
||||||
|
syncobj_handle_to_fd(
|
||||||
|
self.inner.drm.raw(),
|
||||||
|
handle.0,
|
||||||
|
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE | flags,
|
||||||
|
point.0,
|
||||||
|
)
|
||||||
|
.map(Rc::new)
|
||||||
|
.map(SyncFile)
|
||||||
|
};
|
||||||
|
if self.supports_timeline_import() {
|
||||||
|
let res = export(
|
||||||
|
DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE,
|
||||||
|
self.get_handle(syncobj)?,
|
||||||
|
point,
|
||||||
|
);
|
||||||
|
match res {
|
||||||
|
Ok(sf) => return Ok(sf),
|
||||||
|
Err(e) if e.0 == c::EINVAL => {}
|
||||||
|
Err(e) => return Err(DrmError::ExportSyncFile(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let dummy = self.get_dummy()?;
|
||||||
|
let zero = SyncobjPoint(0);
|
||||||
|
self.transfer(
|
||||||
|
syncobj,
|
||||||
|
point,
|
||||||
|
&dummy,
|
||||||
|
zero,
|
||||||
|
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
|
||||||
|
)?;
|
||||||
|
export(0, self.get_handle(&dummy)?, zero).map_err(DrmError::ExportSyncFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transfer(
|
fn transfer(
|
||||||
|
|
@ -259,6 +304,7 @@ impl SyncobjCtx {
|
||||||
src_point: SyncobjPoint,
|
src_point: SyncobjPoint,
|
||||||
dst_syncobj: &Syncobj,
|
dst_syncobj: &Syncobj,
|
||||||
dst_point: SyncobjPoint,
|
dst_point: SyncobjPoint,
|
||||||
|
flags: u32,
|
||||||
) -> Result<(), DrmError> {
|
) -> Result<(), DrmError> {
|
||||||
let src_handle = self.get_handle(src_syncobj)?;
|
let src_handle = self.get_handle(src_syncobj)?;
|
||||||
let dst_handle = self.get_handle(dst_syncobj)?;
|
let dst_handle = self.get_handle(dst_syncobj)?;
|
||||||
|
|
@ -268,7 +314,7 @@ impl SyncobjCtx {
|
||||||
src_point.0,
|
src_point.0,
|
||||||
dst_handle.0,
|
dst_handle.0,
|
||||||
dst_point.0,
|
dst_point.0,
|
||||||
0,
|
flags,
|
||||||
)
|
)
|
||||||
.map_err(DrmError::TransferPoint)
|
.map_err(DrmError::TransferPoint)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1223,6 +1223,7 @@ pub const DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE: u32 = 1 << 0;
|
||||||
pub const DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE: u32 = 1 << 1;
|
pub const DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE: u32 = 1 << 1;
|
||||||
|
|
||||||
pub const DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE: u32 = 1 << 0;
|
pub const DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE: u32 = 1 << 0;
|
||||||
|
pub const DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE: u32 = 1 << 1;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct drm_syncobj_handle {
|
struct drm_syncobj_handle {
|
||||||
|
|
@ -1236,13 +1237,18 @@ struct drm_syncobj_handle {
|
||||||
const DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD: u64 = drm_iowr::<drm_syncobj_handle>(0xC1);
|
const DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD: u64 = drm_iowr::<drm_syncobj_handle>(0xC1);
|
||||||
const DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE: u64 = drm_iowr::<drm_syncobj_handle>(0xC2);
|
const DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE: u64 = drm_iowr::<drm_syncobj_handle>(0xC2);
|
||||||
|
|
||||||
pub fn syncobj_handle_to_fd(drm: c::c_int, handle: u32, flags: u32) -> Result<OwnedFd, OsError> {
|
pub fn syncobj_handle_to_fd(
|
||||||
|
drm: c::c_int,
|
||||||
|
handle: u32,
|
||||||
|
flags: u32,
|
||||||
|
point: u64,
|
||||||
|
) -> Result<OwnedFd, OsError> {
|
||||||
let mut res = drm_syncobj_handle {
|
let mut res = drm_syncobj_handle {
|
||||||
handle,
|
handle,
|
||||||
flags,
|
flags,
|
||||||
fd: 0,
|
fd: 0,
|
||||||
pad: 0,
|
pad: 0,
|
||||||
point: 0,
|
point,
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
ioctl(drm, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &mut res)?;
|
ioctl(drm, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &mut res)?;
|
||||||
|
|
@ -1271,7 +1277,7 @@ pub fn syncobj_fd_to_handle(
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL: u32 = 1 << 0;
|
// pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL: u32 = 1 << 0;
|
||||||
// pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT: u32 = 1 << 1;
|
pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT: u32 = 1 << 1;
|
||||||
pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE: u32 = 1 << 2;
|
pub const DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE: u32 = 1 << 2;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue