diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index d04f696f..bd5decd9 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -9,7 +9,7 @@ use { drm_feedback::DrmFeedback, edid::Descriptor, format::{Format, ARGB8888, XRGB8888}, - gfx_api::{GfxApiOpt, GfxContext, GfxFramebuffer, GfxRenderPass, GfxTexture}, + gfx_api::{BufferResv, GfxApiOpt, GfxContext, GfxFramebuffer, GfxRenderPass, GfxTexture}, ifs::wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC}, renderer::RenderResult, state::State, @@ -350,9 +350,9 @@ pub struct DirectScanoutCache { #[derive(Debug)] pub struct DirectScanoutData { tex: Rc, + _resv: Option>, fb: Rc, dma_buf_id: DmaBufId, - acquired: Cell, position: DirectScanoutPosition, } @@ -366,14 +366,6 @@ pub struct DirectScanoutPosition { pub crtc_height: i32, } -impl Drop for DirectScanoutData { - fn drop(&mut self) { - if self.acquired.replace(false) { - self.tex.reservations().release(); - } - } -} - #[derive(Debug)] pub struct PresentFb { fb: Rc, @@ -532,9 +524,9 @@ impl MetalConnector { if let Some(buffer) = cache.get(&dmabuf.id) { return buffer.fb.as_ref().map(|fb| DirectScanoutData { tex: buffer.tex.upgrade().unwrap(), + _resv: ct.buffer_resv.clone(), fb: fb.clone(), dma_buf_id: dmabuf.id, - acquired: Default::default(), position, }); } @@ -556,9 +548,9 @@ impl MetalConnector { let data = match self.dev.master.add_fb(dmabuf, Some(format.format)) { Ok(fb) => Some(DirectScanoutData { tex: ct.tex.clone(), + _resv: ct.buffer_resv.clone(), fb: Rc::new(fb), dma_buf_id: dmabuf.id, - acquired: Default::default(), position, }), Err(e) => { @@ -780,10 +772,6 @@ impl MetalConnector { Err(()) } else { if let Some(fb) = new_fb { - if let Some(dsd) = &fb.direct_scanout_data { - dsd.tex.reservations().acquire(); - dsd.acquired.set(true); - } self.next_framebuffer.set(Some(fb)); } self.can_present.set(false); diff --git a/src/cursor.rs b/src/cursor.rs index 126923cc..c644f28e 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -378,6 +378,7 @@ fn render_img(image: &InstantiatedCursorImage, renderer: &mut Renderer, x: Fixed None, scale, None, + None, ); } } @@ -391,7 +392,7 @@ impl Cursor for StaticCursor { if let Some(img) = self.image.scales.get(&renderer.scale()) { renderer .base - .render_texture(&img.tex, 0, 0, None, None, renderer.scale(), None); + .render_texture(&img.tex, 0, 0, None, None, renderer.scale(), None, None); } } @@ -421,7 +422,7 @@ impl Cursor for AnimatedCursor { if let Some(img) = img.scales.get(&renderer.scale()) { renderer .base - .render_texture(&img.tex, 0, 0, None, None, renderer.scale(), None); + .render_texture(&img.tex, 0, 0, None, None, renderer.scale(), None, None); } } diff --git a/src/gfx_api.rs b/src/gfx_api.rs index a9f5d280..75fcf245 100644 --- a/src/gfx_api.rs +++ b/src/gfx_api.rs @@ -9,7 +9,7 @@ use { state::State, theme::Color, tree::{Node, OutputNode}, - utils::{numcell::NumCell, transform_ext::TransformExt}, + utils::{clonecell::UnsafeCellCloneSafe, transform_ext::TransformExt}, video::{dmabuf::DmaBuf, gbm::GbmDevice, Modifier}, }, ahash::AHashMap, @@ -21,9 +21,12 @@ use { error::Error, ffi::CString, fmt::{Debug, Formatter}, + ops::Deref, rc::Rc, + sync::atomic::{AtomicU64, Ordering::Relaxed}, }, thiserror::Error, + uapi::OwnedFd, }; pub enum GfxApiOpt { @@ -141,6 +144,34 @@ pub struct CopyTexture { pub tex: Rc, pub source: SampleRect, pub target: FramebufferRect, + pub buffer_resv: Option>, +} + +#[derive(Clone, Debug)] +pub struct SyncFile(pub Rc); + +impl Deref for SyncFile { + type Target = Rc; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +unsafe impl UnsafeCellCloneSafe for SyncFile {} + +pub trait BufferResv: Debug { + fn set_sync_file(&self, user: BufferResvUser, sync_file: &SyncFile); +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub struct BufferResvUser(u64); + +impl Default for BufferResvUser { + fn default() -> Self { + static NEXT_ID: AtomicU64 = AtomicU64::new(1); + Self(NEXT_ID.fetch_add(1, Relaxed)) + } } #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -210,7 +241,7 @@ impl dyn GfxFramebuffer { let mut ops = self.take_render_ops(); let scale = Scale::from_int(1); let mut renderer = self.renderer_base(&mut ops, scale, Transform::None); - renderer.render_texture(texture, x, y, None, None, scale, None); + renderer.render_texture(texture, x, y, None, None, scale, None, None); let clear = self.format().has_alpha.then_some(&Color::TRANSPARENT); self.render(ops, clear); } @@ -376,38 +407,6 @@ pub trait GfxImage { fn height(&self) -> i32; } -#[derive(Default)] -pub struct TextureReservations { - reservations: NumCell, - on_release: Cell>>, -} - -impl TextureReservations { - pub fn has_reservation(&self) -> bool { - self.reservations.get() != 0 - } - - pub fn acquire(&self) { - self.reservations.fetch_add(1); - } - - pub fn release(&self) { - if self.reservations.fetch_sub(1) == 1 { - if let Some(cb) = self.on_release.take() { - cb(); - } - } - } - - pub fn on_released(&self, cb: C) { - if self.has_reservation() { - self.on_release.set(Some(Box::new(cb))); - } else { - cb(); - } - } -} - pub trait GfxTexture: Debug { fn size(&self) -> (i32, i32); fn as_any(&self) -> &dyn Any; @@ -423,7 +422,6 @@ pub trait GfxTexture: Debug { shm: &[Cell], ) -> Result<(), GfxError>; fn dmabuf(&self) -> Option<&DmaBuf>; - fn reservations(&self) -> &TextureReservations; fn format(&self) -> &'static Format; } diff --git a/src/gfx_apis/gl/renderer/context.rs b/src/gfx_apis/gl/renderer/context.rs index b019e555..bba4a6b4 100644 --- a/src/gfx_apis/gl/renderer/context.rs +++ b/src/gfx_apis/gl/renderer/context.rs @@ -186,7 +186,6 @@ impl GlRenderContext { Ok(Rc::new(Texture { ctx: self.clone(), gl, - resv: Default::default(), format, })) } diff --git a/src/gfx_apis/gl/renderer/image.rs b/src/gfx_apis/gl/renderer/image.rs index 4044206d..626d3431 100644 --- a/src/gfx_apis/gl/renderer/image.rs +++ b/src/gfx_apis/gl/renderer/image.rs @@ -27,7 +27,6 @@ impl Image { Ok(Rc::new(Texture { ctx: self.ctx.clone(), gl: GlTexture::import_img(&self.ctx.ctx, &self.gl)?, - resv: Default::default(), format: self.gl.dmabuf.format, })) } diff --git a/src/gfx_apis/gl/renderer/texture.rs b/src/gfx_apis/gl/renderer/texture.rs index efe2b029..7ef887e1 100644 --- a/src/gfx_apis/gl/renderer/texture.rs +++ b/src/gfx_apis/gl/renderer/texture.rs @@ -1,7 +1,7 @@ use { crate::{ format::Format, - gfx_api::{GfxError, GfxTexture, TextureReservations}, + gfx_api::{GfxError, GfxTexture}, gfx_apis::gl::{ gl::texture::GlTexture, renderer::{context::GlRenderContext, framebuffer::Framebuffer}, @@ -20,7 +20,6 @@ use { pub struct Texture { pub(in crate::gfx_apis::gl) ctx: Rc, pub(in crate::gfx_apis::gl) gl: GlTexture, - pub(in crate::gfx_apis::gl) resv: TextureReservations, pub(in crate::gfx_apis::gl) format: &'static Format, } @@ -79,10 +78,6 @@ impl GfxTexture for Texture { self.gl.img.as_ref().map(|i| &i.dmabuf) } - fn reservations(&self) -> &TextureReservations { - &self.resv - } - fn format(&self) -> &'static Format { self.format } diff --git a/src/gfx_apis/vulkan.rs b/src/gfx_apis/vulkan.rs index 9cf7c7b2..83d3ecd2 100644 --- a/src/gfx_apis/vulkan.rs +++ b/src/gfx_apis/vulkan.rs @@ -153,8 +153,6 @@ pub enum VulkanError { IoctlExportSyncFile(#[source] OsError), #[error("Could not import a sync file into a semaphore")] ImportSyncFile(#[source] vk::Result), - #[error("Could not import a sync file into a dma-buf")] - IoctlImportSyncFile(#[source] OsError), #[error("Could not export a sync file from a semaphore")] ExportSyncFile(#[source] vk::Result), #[error("Could not fetch the render node of the device")] diff --git a/src/gfx_apis/vulkan/fence.rs b/src/gfx_apis/vulkan/fence.rs index defa0923..a971e173 100644 --- a/src/gfx_apis/vulkan/fence.rs +++ b/src/gfx_apis/vulkan/fence.rs @@ -1,5 +1,8 @@ use { - crate::gfx_apis::vulkan::{device::VulkanDevice, VulkanError}, + crate::{ + gfx_api::SyncFile, + gfx_apis::vulkan::{device::VulkanDevice, VulkanError}, + }, ash::vk::{ ExportFenceCreateInfo, ExternalFenceHandleTypeFlags, Fence, FenceCreateInfo, FenceGetFdInfoKHR, @@ -38,12 +41,12 @@ impl VulkanDevice { } impl VulkanFence { - pub fn export_syncfile(&self) -> Result, VulkanError> { + pub fn export_sync_file(&self) -> Result { let info = FenceGetFdInfoKHR::builder() .fence(self.fence) .handle_type(ExternalFenceHandleTypeFlags::SYNC_FD); let res = unsafe { self.device.external_fence_fd.get_fence_fd(&info) }; res.map_err(VulkanError::ExportSyncFile) - .map(|fd| Rc::new(OwnedFd::new(fd))) + .map(|fd| SyncFile(Rc::new(OwnedFd::new(fd)))) } } diff --git a/src/gfx_apis/vulkan/image.rs b/src/gfx_apis/vulkan/image.rs index 63f773a5..9385fb1c 100644 --- a/src/gfx_apis/vulkan/image.rs +++ b/src/gfx_apis/vulkan/image.rs @@ -1,7 +1,7 @@ use { crate::{ format::Format, - gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer, GfxImage, GfxTexture, TextureReservations}, + gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer, GfxImage, GfxTexture}, gfx_apis::vulkan::{ allocator::VulkanAllocation, device::VulkanDevice, format::VulkanMaxExtents, renderer::VulkanRenderer, util::OnDrop, VulkanError, @@ -53,7 +53,6 @@ pub struct VulkanImage { pub(super) is_undefined: Cell, pub(super) ty: VulkanImageMemory, pub(super) render_ops: CloneCell>, - pub(super) resv: TextureReservations, } pub enum VulkanImageMemory { @@ -212,7 +211,6 @@ impl VulkanRenderer { is_undefined: Cell::new(true), ty: VulkanImageMemory::Internal(shm), render_ops: Default::default(), - resv: Default::default(), })) } @@ -482,7 +480,6 @@ impl VulkanDmaBufImageTemplate { }), format: self.dmabuf.format, is_undefined: Cell::new(true), - resv: Default::default(), })) } } @@ -587,10 +584,6 @@ impl GfxTexture for VulkanImage { } } - fn reservations(&self) -> &TextureReservations { - &self.resv - } - fn format(&self) -> &'static Format { self.format } diff --git a/src/gfx_apis/vulkan/renderer.rs b/src/gfx_apis/vulkan/renderer.rs index 9948dbf7..39727560 100644 --- a/src/gfx_apis/vulkan/renderer.rs +++ b/src/gfx_apis/vulkan/renderer.rs @@ -2,7 +2,9 @@ use { crate::{ async_engine::SpawnedFuture, format::Format, - gfx_api::{GfxApiOpt, GfxFormat, GfxFramebuffer, GfxTexture}, + gfx_api::{ + BufferResv, BufferResvUser, GfxApiOpt, GfxFormat, GfxFramebuffer, GfxTexture, SyncFile, + }, gfx_apis::vulkan::{ allocator::VulkanAllocator, command::{VulkanCommandBuffer, VulkanCommandPool}, @@ -21,10 +23,7 @@ use { io_uring::IoUring, theme::Color, utils::{copyhashmap::CopyHashMap, errorfmt::ErrorFmt, numcell::NumCell, stack::Stack}, - video::dmabuf::{ - dma_buf_export_sync_file, dma_buf_import_sync_file, DMA_BUF_SYNC_READ, - DMA_BUF_SYNC_WRITE, - }, + video::dmabuf::{dma_buf_export_sync_file, DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE}, }, ahash::AHashMap, ash::{ @@ -49,7 +48,6 @@ use { rc::Rc, slice, }, - uapi::OwnedFd, }; pub struct VulkanRenderer { @@ -66,6 +64,12 @@ pub struct VulkanRenderer { pub(super) pending_frames: CopyHashMap>, pub(super) allocator: Rc, pub(super) last_point: NumCell, + pub(super) buffer_resv_user: BufferResvUser, +} + +pub(super) struct UsedTexture { + tex: Rc, + resv: Option>, } #[derive(Default)] @@ -73,20 +77,20 @@ pub(super) struct Memory { sample: Vec>, flush: Vec>, flush_staging: Vec<(Rc, VulkanStagingBuffer)>, - textures: Vec>, + textures: Vec, image_barriers: Vec, shm_barriers: Vec, wait_semaphores: Vec>, wait_semaphore_infos: Vec, release_fence: Option>, - release_syncfile: Option>, + release_sync_file: Option, } pub(super) struct PendingFrame { point: u64, renderer: Rc, cmd: Cell>>, - _textures: Vec>, + _textures: Vec, _staging: Vec<(Rc, VulkanStagingBuffer)>, wait_semaphores: Cell>>, waiter: Cell>>, @@ -157,6 +161,7 @@ impl VulkanDevice { pending_frames: Default::default(), allocator, last_point: Default::default(), + buffer_resv_user: Default::default(), })) } } @@ -177,7 +182,10 @@ impl VulkanRenderer { } } } - memory.textures.push(tex); + memory.textures.push(UsedTexture { + tex, + resv: c.buffer_resv.clone(), + }); } } } @@ -537,7 +545,7 @@ impl VulkanRenderer { let fd = dma_buf_export_sync_file(&plane.fd, flag) .map_err(VulkanError::IoctlExportSyncFile)?; let semaphore = self.allocate_semaphore()?; - semaphore.import_syncfile(fd)?; + semaphore.import_sync_file(fd)?; infos.push( SemaphoreSubmitInfo::builder() .semaphore(semaphore.semaphore) @@ -553,7 +561,7 @@ impl VulkanRenderer { import( &mut memory.wait_semaphore_infos, &mut memory.wait_semaphores, - texture, + &texture.tex, DMA_BUF_SYNC_READ, )?; } @@ -567,27 +575,25 @@ impl VulkanRenderer { } fn import_release_semaphore(&self, fb: &VulkanImage) { - let memory = self.memory.borrow(); - let syncfile = match memory.release_syncfile.as_ref() { - Some(syncfile) => syncfile, + let memory = &mut *self.memory.borrow_mut(); + let sync_file = match memory.release_sync_file.as_ref() { + Some(sync_file) => sync_file, _ => return, }; - let import = |img: &VulkanImage, flag: u32| { - if let VulkanImageMemory::DmaBuf(buf) = &img.ty { - for plane in &buf.template.dmabuf.planes { - let res = dma_buf_import_sync_file(&plane.fd, flag, &syncfile) - .map_err(VulkanError::IoctlImportSyncFile); - if let Err(e) = res { - log::error!("Could not import syncfile into dmabuf: {}", ErrorFmt(e)); - log::warn!("Relying on implicit sync"); - } + let import = |img: &VulkanImage, resv: Option>, flag: u32| { + if let Some(resv) = resv { + resv.set_sync_file(self.buffer_resv_user, sync_file); + } else if let VulkanImageMemory::DmaBuf(buf) = &img.ty { + if let Err(e) = buf.template.dmabuf.import_sync_file(flag, sync_file) { + log::error!("Could not import sync file into dmabuf: {}", ErrorFmt(e)); + log::warn!("Relying on implicit sync"); } } }; - for texture in &memory.textures { - import(texture, DMA_BUF_SYNC_WRITE); + for texture in &mut memory.textures { + import(&texture.tex, texture.resv.take(), DMA_BUF_SYNC_READ); } - import(fb, DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE); + import(fb, None, DMA_BUF_SYNC_WRITE); } fn submit(&self, buf: CommandBuffer) -> Result<(), VulkanError> { @@ -610,15 +616,15 @@ impl VulkanRenderer { ) .map_err(VulkanError::Submit)?; } - let release_syncfile = match release_fence.export_syncfile() { + let release_sync_file = match release_fence.export_sync_file() { Ok(s) => Some(s), Err(e) => { - log::error!("Could not export syncfile from fence: {}", ErrorFmt(e)); + log::error!("Could not export sync file from fence: {}", ErrorFmt(e)); None } }; memory.release_fence = Some(release_fence); - memory.release_syncfile = release_syncfile; + memory.release_sync_file = release_sync_file; Ok(()) } @@ -650,7 +656,7 @@ impl VulkanRenderer { }); self.pending_frames.set(frame.point, frame.clone()); let future = self.device.instance.eng.spawn(await_release( - memory.release_syncfile.take(), + memory.release_sync_file.take(), self.device.instance.ring.clone(), frame.clone(), self.clone(), @@ -769,7 +775,7 @@ impl VulkanRenderer { let fd = dma_buf_export_sync_file(&plane.fd, DMA_BUF_SYNC_READ) .map_err(VulkanError::IoctlExportSyncFile)?; let semaphore = self.allocate_semaphore()?; - semaphore.import_syncfile(fd)?; + semaphore.import_sync_file(fd)?; let semaphore_info = SemaphoreSubmitInfo::builder() .semaphore(semaphore.semaphore) .stage_mask(PipelineStageFlags2::TOP_OF_PIPE) @@ -841,7 +847,7 @@ impl VulkanRenderer { memory.sample.clear(); memory.wait_semaphores.clear(); memory.release_fence.take(); - memory.release_syncfile.take(); + memory.release_sync_file.take(); } res } @@ -964,14 +970,14 @@ fn image_barrier() -> ImageMemoryBarrier2Builder<'static> { } async fn await_release( - syncfile: Option>, + sync_file: Option, ring: Rc, frame: Rc, renderer: Rc, ) { let mut is_released = false; - if let Some(syncfile) = syncfile { - if let Err(e) = ring.readable(&syncfile).await { + if let Some(sync_file) = sync_file { + if let Err(e) = ring.readable(&sync_file).await { log::error!( "Could not wait for release semaphore to be signaled: {}", ErrorFmt(e) diff --git a/src/gfx_apis/vulkan/semaphore.rs b/src/gfx_apis/vulkan/semaphore.rs index 1d7b3f3c..e9b03681 100644 --- a/src/gfx_apis/vulkan/semaphore.rs +++ b/src/gfx_apis/vulkan/semaphore.rs @@ -36,9 +36,9 @@ impl VulkanDevice { } impl VulkanSemaphore { - pub fn import_syncfile(&self, syncfile: OwnedFd) -> Result<(), VulkanError> { + pub fn import_sync_file(&self, sync_file: OwnedFd) -> Result<(), VulkanError> { let fd_info = ImportSemaphoreFdInfoKHR::builder() - .fd(syncfile.raw()) + .fd(sync_file.raw()) .flags(SemaphoreImportFlags::TEMPORARY) .handle_type(ExternalSemaphoreHandleTypeFlags::SYNC_FD) .semaphore(self.semaphore); @@ -47,7 +47,7 @@ impl VulkanSemaphore { .external_semaphore_fd .import_semaphore_fd(&fd_info) }; - mem::forget(syncfile); + mem::forget(sync_file); res.map_err(VulkanError::ImportSyncFile)?; Ok(()) } diff --git a/src/ifs/wl_buffer.rs b/src/ifs/wl_buffer.rs index 60c347a2..1e5a742f 100644 --- a/src/ifs/wl_buffer.rs +++ b/src/ifs/wl_buffer.rs @@ -35,7 +35,7 @@ pub struct WlBuffer { pub client: Rc, pub rect: Rect, pub format: &'static Format, - dmabuf: Option, + pub dmabuf: Option, render_ctx_version: Cell, pub storage: RefCell>, pub color: Option, diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index c25b2870..e003ff2c 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -16,7 +16,7 @@ use { client::{Client, ClientError, RequestParser}, drm_feedback::DrmFeedback, fixed::Fixed, - gfx_api::SampleRect, + gfx_api::{BufferResv, BufferResvUser, SampleRect, SyncFile}, ifs::{ wl_buffer::WlBuffer, wl_callback::WlCallback, @@ -51,11 +51,13 @@ use { cell_ext::CellExt, clonecell::CloneCell, copyhashmap::CopyHashMap, + errorfmt::ErrorFmt, linkedlist::LinkedList, numcell::NumCell, smallmap::SmallMap, transform_ext::TransformExt, }, + video::dmabuf::DMA_BUF_SYNC_READ, wire::{ wl_surface::*, WlOutputId, WlSurfaceId, ZwpIdleInhibitorV1Id, ZwpLinuxDmabufFeedbackV1Id, @@ -131,6 +133,39 @@ impl NodeVisitorBase for SurfaceSendPreferredTransformVisitor { } } +pub struct SurfaceBuffer { + pub buffer: Rc, + sync_files: SmallMap, +} + +impl Drop for SurfaceBuffer { + fn drop(&mut self) { + let sync_files = self.sync_files.take(); + if let Some(dmabuf) = &self.buffer.dmabuf { + for (_, sync_file) in &sync_files { + if let Err(e) = dmabuf.import_sync_file(DMA_BUF_SYNC_READ, sync_file) { + log::error!("Could not import sync file: {}", ErrorFmt(e)); + } + } + } + if !self.buffer.destroyed() { + self.buffer.send_release(); + } + } +} + +impl Debug for SurfaceBuffer { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SurfaceBuffer").finish_non_exhaustive() + } +} + +impl BufferResv for SurfaceBuffer { + fn set_sync_file(&self, user: BufferResvUser, sync_file: &SyncFile) { + self.sync_files.insert(user, sync_file.clone()); + } +} + pub struct WlSurface { pub id: WlSurfaceId, pub node_id: SurfaceNodeId, @@ -149,7 +184,7 @@ pub struct WlSurface { pub extents: Cell, pub buffer_abs_pos: Cell, pub need_extents_update: Cell, - pub buffer: CloneCell>>, + pub buffer: CloneCell>>, pub buf_x: NumCell, pub buf_y: NumCell, pub children: RefCell>>, @@ -683,11 +718,7 @@ impl WlSurface { } *children = None; } - if let Some(buffer) = self.buffer.set(None) { - if !buffer.destroyed() { - buffer.send_release(); - } - } + self.buffer.set(None); if let Some(xwayland_serial) = self.xwayland_serial.get() { self.client .surfaces_by_xwayland_serial @@ -799,30 +830,15 @@ impl WlSurface { if let Some(buffer_change) = pending.buffer.take() { buffer_changed = true; if let Some(buffer) = self.buffer.take() { - old_raw_size = Some(buffer.rect); - if !buffer.destroyed() { - 'handle_release: { - if let Some(tex) = buffer.texture.get() { - let resv = tex.reservations(); - if resv.has_reservation() { - let buffer = Rc::downgrade(&buffer); - resv.on_released(move || { - if let Some(buffer) = buffer.upgrade() { - if !buffer.destroyed() { - buffer.send_release(); - } - } - }); - break 'handle_release; - } - } - buffer.send_release(); - } - } + old_raw_size = Some(buffer.buffer.rect); } if let Some(buffer) = buffer_change { buffer.update_texture_or_log(); - self.buffer.set(Some(buffer)); + let surface_buffer = SurfaceBuffer { + buffer, + sync_files: Default::default(), + }; + self.buffer.set(Some(Rc::new(surface_buffer))); self.buf_x.fetch_add(dx); self.buf_y.fetch_add(dy); if (dx, dy) != (0, 0) { @@ -872,8 +888,10 @@ impl WlSurface { } if let Some(buffer) = self.buffer.get() { if new_size.is_none() { - let (mut width, mut height) = - self.buffer_transform.get().maybe_swap(buffer.rect.size()); + let (mut width, mut height) = self + .buffer_transform + .get() + .maybe_swap(buffer.buffer.rect.size()); let scale = self.buffer_scale.get(); if scale != 1 { width = (width + scale - 1) / scale; @@ -881,12 +899,14 @@ impl WlSurface { } new_size = Some((width, height)); } - if transform_changed || Some(buffer.rect) != old_raw_size { + if transform_changed || Some(buffer.buffer.rect) != old_raw_size { let (x1, y1, x2, y2) = if self.src_rect.is_none() { (0.0, 0.0, 1.0, 1.0) } else { - let (width, height) = - self.buffer_transform.get().maybe_swap(buffer.rect.size()); + let (width, height) = self + .buffer_transform + .get() + .maybe_swap(buffer.buffer.rect.size()); let width = width as f32; let height = height as f32; let x1 = buffer_points.x1 / width; diff --git a/src/ifs/wl_surface/zwlr_layer_surface_v1.rs b/src/ifs/wl_surface/zwlr_layer_surface_v1.rs index edd0185b..9e6c87e9 100644 --- a/src/ifs/wl_surface/zwlr_layer_surface_v1.rs +++ b/src/ifs/wl_surface/zwlr_layer_surface_v1.rs @@ -350,9 +350,9 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 { } fn after_apply_commit(self: Rc, _pending: &mut PendingState) { - let buffer = self.surface.buffer.get(); + let buffer_is_some = self.surface.buffer.is_some(); if self.mapped.get() { - if buffer.is_none() { + if !buffer_is_some { self.destroy_node(); } else { let pos = self.pos.get(); @@ -361,7 +361,7 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 { self.compute_position(); } } - } else if buffer.is_some() { + } else if buffer_is_some { let layer = &self.output.layers[self.layer.get() as usize]; self.link.set(Some(layer.add_last(self.clone()))); self.mapped.set(true); diff --git a/src/ifs/xdg_toplevel_drag_v1.rs b/src/ifs/xdg_toplevel_drag_v1.rs index 083c51fd..beadf987 100644 --- a/src/ifs/xdg_toplevel_drag_v1.rs +++ b/src/ifs/xdg_toplevel_drag_v1.rs @@ -71,7 +71,7 @@ impl XdgToplevelDragV1 { return Err(XdgToplevelDragV1Error::AlreadyDragged); } if let Some(prev) = self.toplevel.set(Some(toplevel)) { - if prev.xdg.surface.buffer.get().is_some() { + if prev.xdg.surface.buffer.is_some() { return Err(XdgToplevelDragV1Error::ToplevelAttached); } if prev.id != req.toplevel { diff --git a/src/portal/ptr_gui.rs b/src/portal/ptr_gui.rs index 5fbb3793..28190beb 100644 --- a/src/portal/ptr_gui.rs +++ b/src/portal/ptr_gui.rs @@ -222,6 +222,7 @@ impl GuiElement for Button { None, r.scale(), None, + None, ); } } @@ -323,6 +324,7 @@ impl GuiElement for Label { None, r.scale(), None, + None, ); } } diff --git a/src/renderer.rs b/src/renderer.rs index e9999c21..8fe6eeee 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -2,10 +2,10 @@ use { crate::{ gfx_api::{GfxApiOpt, SampleRect}, ifs::{ - wl_buffer::WlBuffer, wl_callback::WlCallback, wl_surface::{ - xdg_surface::XdgSurface, zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, WlSurface, + xdg_surface::XdgSurface, zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, SurfaceBuffer, + WlSurface, }, wp_presentation_feedback::WpPresentationFeedback, }, @@ -152,12 +152,12 @@ impl Renderer<'_> { for title in &rd.titles { let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y); self.base - .render_texture(&title.tex, x, y, None, None, scale, None); + .render_texture(&title.tex, x, y, None, None, scale, None, None); } if let Some(status) = &rd.status { let (x, y) = self.base.scale_point(x + status.tex_x, y + status.tex_y); self.base - .render_texture(&status.tex.texture, x, y, None, None, scale, None); + .render_texture(&status.tex.texture, x, y, None, None, scale, None, None); } } if let Some(ws) = output.workspace.get() { @@ -194,7 +194,7 @@ impl Renderer<'_> { let x = x + (pos.width() - tex_width) / 2; let y = y + (pos.height() - tex_height) / 2; self.base - .render_texture(&tex.texture, x, y, None, None, self.base.scale, None); + .render_texture(&tex.texture, x, y, None, None, self.base.scale, None, None); } } @@ -231,6 +231,7 @@ impl Renderer<'_> { None, self.base.scale, None, + None, ); } } @@ -345,14 +346,14 @@ impl Renderer<'_> { pub fn render_buffer( &mut self, - buffer: &WlBuffer, + buffer: &Rc, x: i32, y: i32, tpoints: SampleRect, tsize: (i32, i32), bounds: Option<&Rect>, ) { - if let Some(tex) = buffer.texture.get() { + if let Some(tex) = buffer.buffer.texture.get() { self.base.render_texture( &tex, x, @@ -361,8 +362,9 @@ impl Renderer<'_> { Some(tsize), self.base.scale, bounds, + Some(buffer.clone()), ); - } else if let Some(color) = &buffer.color { + } else if let Some(color) = &buffer.buffer.color { if let Some(rect) = Rect::new_sized(x, y, tsize.0, tsize.1) { let rect = match bounds { None => rect, @@ -409,8 +411,16 @@ impl Renderer<'_> { self.base.fill_boxes(&title_underline, &uc); if let Some(title) = floating.title_textures.get(&self.base.scale) { let (x, y) = self.base.scale_point(x + bw, y + bw); - self.base - .render_texture(&title.texture, x, y, None, None, self.base.scale, None); + self.base.render_texture( + &title.texture, + x, + y, + None, + None, + self.base.scale, + None, + None, + ); } let body = Rect::new_sized( x + bw, diff --git a/src/renderer/renderer_base.rs b/src/renderer/renderer_base.rs index 9d935d3b..ca9c622b 100644 --- a/src/renderer/renderer_base.rs +++ b/src/renderer/renderer_base.rs @@ -1,6 +1,8 @@ use { crate::{ - gfx_api::{CopyTexture, FillRect, FramebufferRect, GfxApiOpt, GfxTexture, SampleRect}, + gfx_api::{ + BufferResv, CopyTexture, FillRect, FramebufferRect, GfxApiOpt, GfxTexture, SampleRect, + }, rect::Rect, scale::Scale, theme::Color, @@ -130,6 +132,7 @@ impl RendererBase<'_> { tsize: Option<(i32, i32)>, tscale: Scale, bounds: Option<&Rect>, + buffer_resv: Option>, ) { let mut texcoord = tpoints.unwrap_or_else(SampleRect::identity); @@ -154,18 +157,21 @@ impl RendererBase<'_> { } } + let target = FramebufferRect::new( + target_x[0] as f32, + target_y[0] as f32, + target_x[1] as f32, + target_y[1] as f32, + self.transform, + self.fb_width, + self.fb_height, + ); + self.ops.push(GfxApiOpt::CopyTexture(CopyTexture { tex: texture.clone(), source: texcoord, - target: FramebufferRect::new( - target_x[0] as f32, - target_y[0] as f32, - target_x[1] as f32, - target_y[1] as f32, - self.transform, - self.fb_width, - self.fb_height, - ), + target, + buffer_resv, })); } } diff --git a/src/state.rs b/src/state.rs index a1d3ebc2..78849dfe 100644 --- a/src/state.rs +++ b/src/state.rs @@ -408,7 +408,7 @@ impl State { } fn visit_surface(&mut self, node: &Rc) { if let Some(buffer) = node.buffer.get() { - buffer.handle_gfx_context_change(); + buffer.buffer.handle_gfx_context_change(); } node.node_visit_children(self); } @@ -814,6 +814,7 @@ impl State { size, Scale::from_int(1), None, + None, ); if render_hardware_cursors { for seat in self.globals.lock_seats().values() { diff --git a/src/video/dmabuf.rs b/src/video/dmabuf.rs index c217bfba..4ef66a96 100644 --- a/src/video/dmabuf.rs +++ b/src/video/dmabuf.rs @@ -48,6 +48,13 @@ impl DmaBuf { } false } + + pub fn import_sync_file(&self, flags: u32, sync_file: &OwnedFd) -> Result<(), OsError> { + for plane in &self.planes { + dma_buf_import_sync_file(&plane.fd, flags, sync_file)?; + } + Ok(()) + } } const DMA_BUF_BASE: u64 = b'b' as _;