1
0
Fork 0
forked from wry/wry

render: remove TextureReservations

This commit is contained in:
Julian Orth 2024-03-21 14:48:24 +01:00
parent 300deecc7d
commit ea4a1f027b
20 changed files with 198 additions and 172 deletions

View file

@ -9,7 +9,7 @@ use {
drm_feedback::DrmFeedback, drm_feedback::DrmFeedback,
edid::Descriptor, edid::Descriptor,
format::{Format, ARGB8888, XRGB8888}, 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}, ifs::wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC},
renderer::RenderResult, renderer::RenderResult,
state::State, state::State,
@ -350,9 +350,9 @@ pub struct DirectScanoutCache {
#[derive(Debug)] #[derive(Debug)]
pub struct DirectScanoutData { pub struct DirectScanoutData {
tex: Rc<dyn GfxTexture>, tex: Rc<dyn GfxTexture>,
_resv: Option<Rc<dyn BufferResv>>,
fb: Rc<DrmFramebuffer>, fb: Rc<DrmFramebuffer>,
dma_buf_id: DmaBufId, dma_buf_id: DmaBufId,
acquired: Cell<bool>,
position: DirectScanoutPosition, position: DirectScanoutPosition,
} }
@ -366,14 +366,6 @@ pub struct DirectScanoutPosition {
pub crtc_height: i32, pub crtc_height: i32,
} }
impl Drop for DirectScanoutData {
fn drop(&mut self) {
if self.acquired.replace(false) {
self.tex.reservations().release();
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct PresentFb { pub struct PresentFb {
fb: Rc<DrmFramebuffer>, fb: Rc<DrmFramebuffer>,
@ -532,9 +524,9 @@ impl MetalConnector {
if let Some(buffer) = cache.get(&dmabuf.id) { if let Some(buffer) = cache.get(&dmabuf.id) {
return buffer.fb.as_ref().map(|fb| DirectScanoutData { return buffer.fb.as_ref().map(|fb| DirectScanoutData {
tex: buffer.tex.upgrade().unwrap(), tex: buffer.tex.upgrade().unwrap(),
_resv: ct.buffer_resv.clone(),
fb: fb.clone(), fb: fb.clone(),
dma_buf_id: dmabuf.id, dma_buf_id: dmabuf.id,
acquired: Default::default(),
position, position,
}); });
} }
@ -556,9 +548,9 @@ impl MetalConnector {
let data = match self.dev.master.add_fb(dmabuf, Some(format.format)) { let data = match self.dev.master.add_fb(dmabuf, Some(format.format)) {
Ok(fb) => Some(DirectScanoutData { Ok(fb) => Some(DirectScanoutData {
tex: ct.tex.clone(), tex: ct.tex.clone(),
_resv: ct.buffer_resv.clone(),
fb: Rc::new(fb), fb: Rc::new(fb),
dma_buf_id: dmabuf.id, dma_buf_id: dmabuf.id,
acquired: Default::default(),
position, position,
}), }),
Err(e) => { Err(e) => {
@ -780,10 +772,6 @@ impl MetalConnector {
Err(()) Err(())
} else { } else {
if let Some(fb) = new_fb { 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.next_framebuffer.set(Some(fb));
} }
self.can_present.set(false); self.can_present.set(false);

View file

@ -378,6 +378,7 @@ fn render_img(image: &InstantiatedCursorImage, renderer: &mut Renderer, x: Fixed
None, None,
scale, scale,
None, None,
None,
); );
} }
} }
@ -391,7 +392,7 @@ impl Cursor for StaticCursor {
if let Some(img) = self.image.scales.get(&renderer.scale()) { if let Some(img) = self.image.scales.get(&renderer.scale()) {
renderer renderer
.base .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()) { if let Some(img) = img.scales.get(&renderer.scale()) {
renderer renderer
.base .base
.render_texture(&img.tex, 0, 0, None, None, renderer.scale(), None); .render_texture(&img.tex, 0, 0, None, None, renderer.scale(), None, None);
} }
} }

View file

@ -9,7 +9,7 @@ use {
state::State, state::State,
theme::Color, theme::Color,
tree::{Node, OutputNode}, tree::{Node, OutputNode},
utils::{numcell::NumCell, transform_ext::TransformExt}, utils::{clonecell::UnsafeCellCloneSafe, transform_ext::TransformExt},
video::{dmabuf::DmaBuf, gbm::GbmDevice, Modifier}, video::{dmabuf::DmaBuf, gbm::GbmDevice, Modifier},
}, },
ahash::AHashMap, ahash::AHashMap,
@ -21,9 +21,12 @@ use {
error::Error, error::Error,
ffi::CString, ffi::CString,
fmt::{Debug, Formatter}, fmt::{Debug, Formatter},
ops::Deref,
rc::Rc, rc::Rc,
sync::atomic::{AtomicU64, Ordering::Relaxed},
}, },
thiserror::Error, thiserror::Error,
uapi::OwnedFd,
}; };
pub enum GfxApiOpt { pub enum GfxApiOpt {
@ -141,6 +144,34 @@ pub struct CopyTexture {
pub tex: Rc<dyn GfxTexture>, pub tex: Rc<dyn GfxTexture>,
pub source: SampleRect, pub source: SampleRect,
pub target: FramebufferRect, pub target: FramebufferRect,
pub buffer_resv: Option<Rc<dyn BufferResv>>,
}
#[derive(Clone, Debug)]
pub struct SyncFile(pub Rc<OwnedFd>);
impl Deref for SyncFile {
type Target = Rc<OwnedFd>;
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)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -210,7 +241,7 @@ impl dyn GfxFramebuffer {
let mut ops = self.take_render_ops(); let mut ops = self.take_render_ops();
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);
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); let clear = self.format().has_alpha.then_some(&Color::TRANSPARENT);
self.render(ops, clear); self.render(ops, clear);
} }
@ -376,38 +407,6 @@ pub trait GfxImage {
fn height(&self) -> i32; fn height(&self) -> i32;
} }
#[derive(Default)]
pub struct TextureReservations {
reservations: NumCell<usize>,
on_release: Cell<Option<Box<dyn FnOnce()>>>,
}
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<C: FnOnce() + 'static>(&self, cb: C) {
if self.has_reservation() {
self.on_release.set(Some(Box::new(cb)));
} else {
cb();
}
}
}
pub trait GfxTexture: Debug { pub trait GfxTexture: Debug {
fn size(&self) -> (i32, i32); fn size(&self) -> (i32, i32);
fn as_any(&self) -> &dyn Any; fn as_any(&self) -> &dyn Any;
@ -423,7 +422,6 @@ pub trait GfxTexture: Debug {
shm: &[Cell<u8>], shm: &[Cell<u8>],
) -> Result<(), GfxError>; ) -> Result<(), GfxError>;
fn dmabuf(&self) -> Option<&DmaBuf>; fn dmabuf(&self) -> Option<&DmaBuf>;
fn reservations(&self) -> &TextureReservations;
fn format(&self) -> &'static Format; fn format(&self) -> &'static Format;
} }

View file

@ -186,7 +186,6 @@ impl GlRenderContext {
Ok(Rc::new(Texture { Ok(Rc::new(Texture {
ctx: self.clone(), ctx: self.clone(),
gl, gl,
resv: Default::default(),
format, format,
})) }))
} }

View file

@ -27,7 +27,6 @@ impl Image {
Ok(Rc::new(Texture { Ok(Rc::new(Texture {
ctx: self.ctx.clone(), ctx: self.ctx.clone(),
gl: GlTexture::import_img(&self.ctx.ctx, &self.gl)?, gl: GlTexture::import_img(&self.ctx.ctx, &self.gl)?,
resv: Default::default(),
format: self.gl.dmabuf.format, format: self.gl.dmabuf.format,
})) }))
} }

View file

@ -1,7 +1,7 @@
use { use {
crate::{ crate::{
format::Format, format::Format,
gfx_api::{GfxError, GfxTexture, TextureReservations}, gfx_api::{GfxError, GfxTexture},
gfx_apis::gl::{ gfx_apis::gl::{
gl::texture::GlTexture, gl::texture::GlTexture,
renderer::{context::GlRenderContext, framebuffer::Framebuffer}, renderer::{context::GlRenderContext, framebuffer::Framebuffer},
@ -20,7 +20,6 @@ use {
pub struct Texture { pub struct Texture {
pub(in crate::gfx_apis::gl) ctx: Rc<GlRenderContext>, pub(in crate::gfx_apis::gl) ctx: Rc<GlRenderContext>,
pub(in crate::gfx_apis::gl) gl: GlTexture, 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, 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) self.gl.img.as_ref().map(|i| &i.dmabuf)
} }
fn reservations(&self) -> &TextureReservations {
&self.resv
}
fn format(&self) -> &'static Format { fn format(&self) -> &'static Format {
self.format self.format
} }

View file

@ -153,8 +153,6 @@ pub enum VulkanError {
IoctlExportSyncFile(#[source] OsError), IoctlExportSyncFile(#[source] OsError),
#[error("Could not import a sync file into a semaphore")] #[error("Could not import a sync file into a semaphore")]
ImportSyncFile(#[source] vk::Result), 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")] #[error("Could not export a sync file from a semaphore")]
ExportSyncFile(#[source] vk::Result), ExportSyncFile(#[source] vk::Result),
#[error("Could not fetch the render node of the device")] #[error("Could not fetch the render node of the device")]

View file

@ -1,5 +1,8 @@
use { use {
crate::gfx_apis::vulkan::{device::VulkanDevice, VulkanError}, crate::{
gfx_api::SyncFile,
gfx_apis::vulkan::{device::VulkanDevice, VulkanError},
},
ash::vk::{ ash::vk::{
ExportFenceCreateInfo, ExternalFenceHandleTypeFlags, Fence, FenceCreateInfo, ExportFenceCreateInfo, ExternalFenceHandleTypeFlags, Fence, FenceCreateInfo,
FenceGetFdInfoKHR, FenceGetFdInfoKHR,
@ -38,12 +41,12 @@ impl VulkanDevice {
} }
impl VulkanFence { impl VulkanFence {
pub fn export_syncfile(&self) -> Result<Rc<OwnedFd>, VulkanError> { pub fn export_sync_file(&self) -> Result<SyncFile, VulkanError> {
let info = FenceGetFdInfoKHR::builder() let info = FenceGetFdInfoKHR::builder()
.fence(self.fence) .fence(self.fence)
.handle_type(ExternalFenceHandleTypeFlags::SYNC_FD); .handle_type(ExternalFenceHandleTypeFlags::SYNC_FD);
let res = unsafe { self.device.external_fence_fd.get_fence_fd(&info) }; let res = unsafe { self.device.external_fence_fd.get_fence_fd(&info) };
res.map_err(VulkanError::ExportSyncFile) res.map_err(VulkanError::ExportSyncFile)
.map(|fd| Rc::new(OwnedFd::new(fd))) .map(|fd| SyncFile(Rc::new(OwnedFd::new(fd))))
} }
} }

View file

@ -1,7 +1,7 @@
use { use {
crate::{ crate::{
format::Format, format::Format,
gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer, GfxImage, GfxTexture, TextureReservations}, gfx_api::{GfxApiOpt, GfxError, GfxFramebuffer, GfxImage, GfxTexture},
gfx_apis::vulkan::{ gfx_apis::vulkan::{
allocator::VulkanAllocation, device::VulkanDevice, format::VulkanMaxExtents, allocator::VulkanAllocation, device::VulkanDevice, format::VulkanMaxExtents,
renderer::VulkanRenderer, util::OnDrop, VulkanError, renderer::VulkanRenderer, util::OnDrop, VulkanError,
@ -53,7 +53,6 @@ pub struct VulkanImage {
pub(super) is_undefined: Cell<bool>, pub(super) is_undefined: Cell<bool>,
pub(super) ty: VulkanImageMemory, pub(super) ty: VulkanImageMemory,
pub(super) render_ops: CloneCell<Vec<GfxApiOpt>>, pub(super) render_ops: CloneCell<Vec<GfxApiOpt>>,
pub(super) resv: TextureReservations,
} }
pub enum VulkanImageMemory { pub enum VulkanImageMemory {
@ -212,7 +211,6 @@ impl VulkanRenderer {
is_undefined: Cell::new(true), is_undefined: Cell::new(true),
ty: VulkanImageMemory::Internal(shm), ty: VulkanImageMemory::Internal(shm),
render_ops: Default::default(), render_ops: Default::default(),
resv: Default::default(),
})) }))
} }
@ -482,7 +480,6 @@ impl VulkanDmaBufImageTemplate {
}), }),
format: self.dmabuf.format, format: self.dmabuf.format,
is_undefined: Cell::new(true), 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 { fn format(&self) -> &'static Format {
self.format self.format
} }

View file

@ -2,7 +2,9 @@ use {
crate::{ crate::{
async_engine::SpawnedFuture, async_engine::SpawnedFuture,
format::Format, format::Format,
gfx_api::{GfxApiOpt, GfxFormat, GfxFramebuffer, GfxTexture}, gfx_api::{
BufferResv, BufferResvUser, GfxApiOpt, GfxFormat, GfxFramebuffer, GfxTexture, SyncFile,
},
gfx_apis::vulkan::{ gfx_apis::vulkan::{
allocator::VulkanAllocator, allocator::VulkanAllocator,
command::{VulkanCommandBuffer, VulkanCommandPool}, command::{VulkanCommandBuffer, VulkanCommandPool},
@ -21,10 +23,7 @@ use {
io_uring::IoUring, io_uring::IoUring,
theme::Color, theme::Color,
utils::{copyhashmap::CopyHashMap, errorfmt::ErrorFmt, numcell::NumCell, stack::Stack}, utils::{copyhashmap::CopyHashMap, errorfmt::ErrorFmt, numcell::NumCell, stack::Stack},
video::dmabuf::{ video::dmabuf::{dma_buf_export_sync_file, DMA_BUF_SYNC_READ, DMA_BUF_SYNC_WRITE},
dma_buf_export_sync_file, dma_buf_import_sync_file, DMA_BUF_SYNC_READ,
DMA_BUF_SYNC_WRITE,
},
}, },
ahash::AHashMap, ahash::AHashMap,
ash::{ ash::{
@ -49,7 +48,6 @@ use {
rc::Rc, rc::Rc,
slice, slice,
}, },
uapi::OwnedFd,
}; };
pub struct VulkanRenderer { pub struct VulkanRenderer {
@ -66,6 +64,12 @@ pub struct VulkanRenderer {
pub(super) pending_frames: CopyHashMap<u64, Rc<PendingFrame>>, pub(super) pending_frames: CopyHashMap<u64, Rc<PendingFrame>>,
pub(super) allocator: Rc<VulkanAllocator>, pub(super) allocator: Rc<VulkanAllocator>,
pub(super) last_point: NumCell<u64>, pub(super) last_point: NumCell<u64>,
pub(super) buffer_resv_user: BufferResvUser,
}
pub(super) struct UsedTexture {
tex: Rc<VulkanImage>,
resv: Option<Rc<dyn BufferResv>>,
} }
#[derive(Default)] #[derive(Default)]
@ -73,20 +77,20 @@ pub(super) struct Memory {
sample: Vec<Rc<VulkanImage>>, sample: Vec<Rc<VulkanImage>>,
flush: Vec<Rc<VulkanImage>>, flush: Vec<Rc<VulkanImage>>,
flush_staging: Vec<(Rc<VulkanImage>, VulkanStagingBuffer)>, flush_staging: Vec<(Rc<VulkanImage>, VulkanStagingBuffer)>,
textures: Vec<Rc<VulkanImage>>, textures: Vec<UsedTexture>,
image_barriers: Vec<ImageMemoryBarrier2>, image_barriers: Vec<ImageMemoryBarrier2>,
shm_barriers: Vec<BufferMemoryBarrier2>, shm_barriers: Vec<BufferMemoryBarrier2>,
wait_semaphores: Vec<Rc<VulkanSemaphore>>, wait_semaphores: Vec<Rc<VulkanSemaphore>>,
wait_semaphore_infos: Vec<SemaphoreSubmitInfo>, wait_semaphore_infos: Vec<SemaphoreSubmitInfo>,
release_fence: Option<Rc<VulkanFence>>, release_fence: Option<Rc<VulkanFence>>,
release_syncfile: Option<Rc<OwnedFd>>, release_sync_file: Option<SyncFile>,
} }
pub(super) struct PendingFrame { pub(super) struct PendingFrame {
point: u64, point: u64,
renderer: Rc<VulkanRenderer>, renderer: Rc<VulkanRenderer>,
cmd: Cell<Option<Rc<VulkanCommandBuffer>>>, cmd: Cell<Option<Rc<VulkanCommandBuffer>>>,
_textures: Vec<Rc<VulkanImage>>, _textures: Vec<UsedTexture>,
_staging: Vec<(Rc<VulkanImage>, VulkanStagingBuffer)>, _staging: Vec<(Rc<VulkanImage>, VulkanStagingBuffer)>,
wait_semaphores: Cell<Vec<Rc<VulkanSemaphore>>>, wait_semaphores: Cell<Vec<Rc<VulkanSemaphore>>>,
waiter: Cell<Option<SpawnedFuture<()>>>, waiter: Cell<Option<SpawnedFuture<()>>>,
@ -157,6 +161,7 @@ impl VulkanDevice {
pending_frames: Default::default(), pending_frames: Default::default(),
allocator, allocator,
last_point: Default::default(), 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) let fd = dma_buf_export_sync_file(&plane.fd, flag)
.map_err(VulkanError::IoctlExportSyncFile)?; .map_err(VulkanError::IoctlExportSyncFile)?;
let semaphore = self.allocate_semaphore()?; let semaphore = self.allocate_semaphore()?;
semaphore.import_syncfile(fd)?; semaphore.import_sync_file(fd)?;
infos.push( infos.push(
SemaphoreSubmitInfo::builder() SemaphoreSubmitInfo::builder()
.semaphore(semaphore.semaphore) .semaphore(semaphore.semaphore)
@ -553,7 +561,7 @@ impl VulkanRenderer {
import( import(
&mut memory.wait_semaphore_infos, &mut memory.wait_semaphore_infos,
&mut memory.wait_semaphores, &mut memory.wait_semaphores,
texture, &texture.tex,
DMA_BUF_SYNC_READ, DMA_BUF_SYNC_READ,
)?; )?;
} }
@ -567,27 +575,25 @@ impl VulkanRenderer {
} }
fn import_release_semaphore(&self, fb: &VulkanImage) { fn import_release_semaphore(&self, fb: &VulkanImage) {
let memory = self.memory.borrow(); let memory = &mut *self.memory.borrow_mut();
let syncfile = match memory.release_syncfile.as_ref() { let sync_file = match memory.release_sync_file.as_ref() {
Some(syncfile) => syncfile, Some(sync_file) => sync_file,
_ => return, _ => return,
}; };
let import = |img: &VulkanImage, flag: u32| { let import = |img: &VulkanImage, resv: Option<Rc<dyn BufferResv>>, flag: u32| {
if let VulkanImageMemory::DmaBuf(buf) = &img.ty { if let Some(resv) = resv {
for plane in &buf.template.dmabuf.planes { resv.set_sync_file(self.buffer_resv_user, sync_file);
let res = dma_buf_import_sync_file(&plane.fd, flag, &syncfile) } else if let VulkanImageMemory::DmaBuf(buf) = &img.ty {
.map_err(VulkanError::IoctlImportSyncFile); if let Err(e) = buf.template.dmabuf.import_sync_file(flag, sync_file) {
if let Err(e) = res { log::error!("Could not import sync file into dmabuf: {}", ErrorFmt(e));
log::error!("Could not import syncfile into dmabuf: {}", ErrorFmt(e)); log::warn!("Relying on implicit sync");
log::warn!("Relying on implicit sync");
}
} }
} }
}; };
for texture in &memory.textures { for texture in &mut memory.textures {
import(texture, DMA_BUF_SYNC_WRITE); 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> { fn submit(&self, buf: CommandBuffer) -> Result<(), VulkanError> {
@ -610,15 +616,15 @@ impl VulkanRenderer {
) )
.map_err(VulkanError::Submit)?; .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), Ok(s) => Some(s),
Err(e) => { Err(e) => {
log::error!("Could not export syncfile from fence: {}", ErrorFmt(e)); log::error!("Could not export sync file from fence: {}", ErrorFmt(e));
None None
} }
}; };
memory.release_fence = Some(release_fence); memory.release_fence = Some(release_fence);
memory.release_syncfile = release_syncfile; memory.release_sync_file = release_sync_file;
Ok(()) Ok(())
} }
@ -650,7 +656,7 @@ impl VulkanRenderer {
}); });
self.pending_frames.set(frame.point, frame.clone()); self.pending_frames.set(frame.point, frame.clone());
let future = self.device.instance.eng.spawn(await_release( let future = self.device.instance.eng.spawn(await_release(
memory.release_syncfile.take(), memory.release_sync_file.take(),
self.device.instance.ring.clone(), self.device.instance.ring.clone(),
frame.clone(), frame.clone(),
self.clone(), self.clone(),
@ -769,7 +775,7 @@ impl VulkanRenderer {
let fd = dma_buf_export_sync_file(&plane.fd, DMA_BUF_SYNC_READ) let fd = dma_buf_export_sync_file(&plane.fd, DMA_BUF_SYNC_READ)
.map_err(VulkanError::IoctlExportSyncFile)?; .map_err(VulkanError::IoctlExportSyncFile)?;
let semaphore = self.allocate_semaphore()?; let semaphore = self.allocate_semaphore()?;
semaphore.import_syncfile(fd)?; semaphore.import_sync_file(fd)?;
let semaphore_info = SemaphoreSubmitInfo::builder() let semaphore_info = SemaphoreSubmitInfo::builder()
.semaphore(semaphore.semaphore) .semaphore(semaphore.semaphore)
.stage_mask(PipelineStageFlags2::TOP_OF_PIPE) .stage_mask(PipelineStageFlags2::TOP_OF_PIPE)
@ -841,7 +847,7 @@ impl VulkanRenderer {
memory.sample.clear(); memory.sample.clear();
memory.wait_semaphores.clear(); memory.wait_semaphores.clear();
memory.release_fence.take(); memory.release_fence.take();
memory.release_syncfile.take(); memory.release_sync_file.take();
} }
res res
} }
@ -964,14 +970,14 @@ fn image_barrier() -> ImageMemoryBarrier2Builder<'static> {
} }
async fn await_release( async fn await_release(
syncfile: Option<Rc<OwnedFd>>, sync_file: Option<SyncFile>,
ring: Rc<IoUring>, ring: Rc<IoUring>,
frame: Rc<PendingFrame>, frame: Rc<PendingFrame>,
renderer: Rc<VulkanRenderer>, renderer: Rc<VulkanRenderer>,
) { ) {
let mut is_released = false; let mut is_released = false;
if let Some(syncfile) = syncfile { if let Some(sync_file) = sync_file {
if let Err(e) = ring.readable(&syncfile).await { if let Err(e) = ring.readable(&sync_file).await {
log::error!( log::error!(
"Could not wait for release semaphore to be signaled: {}", "Could not wait for release semaphore to be signaled: {}",
ErrorFmt(e) ErrorFmt(e)

View file

@ -36,9 +36,9 @@ impl VulkanDevice {
} }
impl VulkanSemaphore { 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() let fd_info = ImportSemaphoreFdInfoKHR::builder()
.fd(syncfile.raw()) .fd(sync_file.raw())
.flags(SemaphoreImportFlags::TEMPORARY) .flags(SemaphoreImportFlags::TEMPORARY)
.handle_type(ExternalSemaphoreHandleTypeFlags::SYNC_FD) .handle_type(ExternalSemaphoreHandleTypeFlags::SYNC_FD)
.semaphore(self.semaphore); .semaphore(self.semaphore);
@ -47,7 +47,7 @@ impl VulkanSemaphore {
.external_semaphore_fd .external_semaphore_fd
.import_semaphore_fd(&fd_info) .import_semaphore_fd(&fd_info)
}; };
mem::forget(syncfile); mem::forget(sync_file);
res.map_err(VulkanError::ImportSyncFile)?; res.map_err(VulkanError::ImportSyncFile)?;
Ok(()) Ok(())
} }

View file

@ -35,7 +35,7 @@ pub struct WlBuffer {
pub client: Rc<Client>, pub client: Rc<Client>,
pub rect: Rect, pub rect: Rect,
pub format: &'static Format, pub format: &'static Format,
dmabuf: Option<DmaBuf>, pub dmabuf: Option<DmaBuf>,
render_ctx_version: Cell<u32>, render_ctx_version: Cell<u32>,
pub storage: RefCell<Option<WlBufferStorage>>, pub storage: RefCell<Option<WlBufferStorage>>,
pub color: Option<Color>, pub color: Option<Color>,

View file

@ -16,7 +16,7 @@ use {
client::{Client, ClientError, RequestParser}, client::{Client, ClientError, RequestParser},
drm_feedback::DrmFeedback, drm_feedback::DrmFeedback,
fixed::Fixed, fixed::Fixed,
gfx_api::SampleRect, gfx_api::{BufferResv, BufferResvUser, SampleRect, SyncFile},
ifs::{ ifs::{
wl_buffer::WlBuffer, wl_buffer::WlBuffer,
wl_callback::WlCallback, wl_callback::WlCallback,
@ -51,11 +51,13 @@ use {
cell_ext::CellExt, cell_ext::CellExt,
clonecell::CloneCell, clonecell::CloneCell,
copyhashmap::CopyHashMap, copyhashmap::CopyHashMap,
errorfmt::ErrorFmt,
linkedlist::LinkedList, linkedlist::LinkedList,
numcell::NumCell, numcell::NumCell,
smallmap::SmallMap, smallmap::SmallMap,
transform_ext::TransformExt, transform_ext::TransformExt,
}, },
video::dmabuf::DMA_BUF_SYNC_READ,
wire::{ wire::{
wl_surface::*, WlOutputId, WlSurfaceId, ZwpIdleInhibitorV1Id, wl_surface::*, WlOutputId, WlSurfaceId, ZwpIdleInhibitorV1Id,
ZwpLinuxDmabufFeedbackV1Id, ZwpLinuxDmabufFeedbackV1Id,
@ -131,6 +133,39 @@ impl NodeVisitorBase for SurfaceSendPreferredTransformVisitor {
} }
} }
pub struct SurfaceBuffer {
pub buffer: Rc<WlBuffer>,
sync_files: SmallMap<BufferResvUser, SyncFile, 1>,
}
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 struct WlSurface {
pub id: WlSurfaceId, pub id: WlSurfaceId,
pub node_id: SurfaceNodeId, pub node_id: SurfaceNodeId,
@ -149,7 +184,7 @@ pub struct WlSurface {
pub extents: Cell<Rect>, pub extents: Cell<Rect>,
pub buffer_abs_pos: Cell<Rect>, pub buffer_abs_pos: Cell<Rect>,
pub need_extents_update: Cell<bool>, pub need_extents_update: Cell<bool>,
pub buffer: CloneCell<Option<Rc<WlBuffer>>>, pub buffer: CloneCell<Option<Rc<SurfaceBuffer>>>,
pub buf_x: NumCell<i32>, pub buf_x: NumCell<i32>,
pub buf_y: NumCell<i32>, pub buf_y: NumCell<i32>,
pub children: RefCell<Option<Box<ParentData>>>, pub children: RefCell<Option<Box<ParentData>>>,
@ -683,11 +718,7 @@ impl WlSurface {
} }
*children = None; *children = None;
} }
if let Some(buffer) = self.buffer.set(None) { self.buffer.set(None);
if !buffer.destroyed() {
buffer.send_release();
}
}
if let Some(xwayland_serial) = self.xwayland_serial.get() { if let Some(xwayland_serial) = self.xwayland_serial.get() {
self.client self.client
.surfaces_by_xwayland_serial .surfaces_by_xwayland_serial
@ -799,30 +830,15 @@ impl WlSurface {
if let Some(buffer_change) = pending.buffer.take() { if let Some(buffer_change) = pending.buffer.take() {
buffer_changed = true; buffer_changed = true;
if let Some(buffer) = self.buffer.take() { if let Some(buffer) = self.buffer.take() {
old_raw_size = Some(buffer.rect); old_raw_size = Some(buffer.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();
}
}
} }
if let Some(buffer) = buffer_change { if let Some(buffer) = buffer_change {
buffer.update_texture_or_log(); 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_x.fetch_add(dx);
self.buf_y.fetch_add(dy); self.buf_y.fetch_add(dy);
if (dx, dy) != (0, 0) { if (dx, dy) != (0, 0) {
@ -872,8 +888,10 @@ impl WlSurface {
} }
if let Some(buffer) = self.buffer.get() { if let Some(buffer) = self.buffer.get() {
if new_size.is_none() { if new_size.is_none() {
let (mut width, mut height) = let (mut width, mut height) = self
self.buffer_transform.get().maybe_swap(buffer.rect.size()); .buffer_transform
.get()
.maybe_swap(buffer.buffer.rect.size());
let scale = self.buffer_scale.get(); let scale = self.buffer_scale.get();
if scale != 1 { if scale != 1 {
width = (width + scale - 1) / scale; width = (width + scale - 1) / scale;
@ -881,12 +899,14 @@ impl WlSurface {
} }
new_size = Some((width, height)); 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() { let (x1, y1, x2, y2) = if self.src_rect.is_none() {
(0.0, 0.0, 1.0, 1.0) (0.0, 0.0, 1.0, 1.0)
} else { } else {
let (width, height) = let (width, height) = self
self.buffer_transform.get().maybe_swap(buffer.rect.size()); .buffer_transform
.get()
.maybe_swap(buffer.buffer.rect.size());
let width = width as f32; let width = width as f32;
let height = height as f32; let height = height as f32;
let x1 = buffer_points.x1 / width; let x1 = buffer_points.x1 / width;

View file

@ -350,9 +350,9 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 {
} }
fn after_apply_commit(self: Rc<Self>, _pending: &mut PendingState) { fn after_apply_commit(self: Rc<Self>, _pending: &mut PendingState) {
let buffer = self.surface.buffer.get(); let buffer_is_some = self.surface.buffer.is_some();
if self.mapped.get() { if self.mapped.get() {
if buffer.is_none() { if !buffer_is_some {
self.destroy_node(); self.destroy_node();
} else { } else {
let pos = self.pos.get(); let pos = self.pos.get();
@ -361,7 +361,7 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 {
self.compute_position(); self.compute_position();
} }
} }
} else if buffer.is_some() { } else if buffer_is_some {
let layer = &self.output.layers[self.layer.get() as usize]; let layer = &self.output.layers[self.layer.get() as usize];
self.link.set(Some(layer.add_last(self.clone()))); self.link.set(Some(layer.add_last(self.clone())));
self.mapped.set(true); self.mapped.set(true);

View file

@ -71,7 +71,7 @@ impl XdgToplevelDragV1 {
return Err(XdgToplevelDragV1Error::AlreadyDragged); return Err(XdgToplevelDragV1Error::AlreadyDragged);
} }
if let Some(prev) = self.toplevel.set(Some(toplevel)) { 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); return Err(XdgToplevelDragV1Error::ToplevelAttached);
} }
if prev.id != req.toplevel { if prev.id != req.toplevel {

View file

@ -222,6 +222,7 @@ impl GuiElement for Button {
None, None,
r.scale(), r.scale(),
None, None,
None,
); );
} }
} }
@ -323,6 +324,7 @@ impl GuiElement for Label {
None, None,
r.scale(), r.scale(),
None, None,
None,
); );
} }
} }

View file

@ -2,10 +2,10 @@ use {
crate::{ crate::{
gfx_api::{GfxApiOpt, SampleRect}, gfx_api::{GfxApiOpt, SampleRect},
ifs::{ ifs::{
wl_buffer::WlBuffer,
wl_callback::WlCallback, wl_callback::WlCallback,
wl_surface::{ 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, wp_presentation_feedback::WpPresentationFeedback,
}, },
@ -152,12 +152,12 @@ impl Renderer<'_> {
for title in &rd.titles { for title in &rd.titles {
let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y); let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y);
self.base 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 { if let Some(status) = &rd.status {
let (x, y) = self.base.scale_point(x + status.tex_x, y + status.tex_y); let (x, y) = self.base.scale_point(x + status.tex_x, y + status.tex_y);
self.base 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() { if let Some(ws) = output.workspace.get() {
@ -194,7 +194,7 @@ impl Renderer<'_> {
let x = x + (pos.width() - tex_width) / 2; let x = x + (pos.width() - tex_width) / 2;
let y = y + (pos.height() - tex_height) / 2; let y = y + (pos.height() - tex_height) / 2;
self.base 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, None,
self.base.scale, self.base.scale,
None, None,
None,
); );
} }
} }
@ -345,14 +346,14 @@ impl Renderer<'_> {
pub fn render_buffer( pub fn render_buffer(
&mut self, &mut self,
buffer: &WlBuffer, buffer: &Rc<SurfaceBuffer>,
x: i32, x: i32,
y: i32, y: i32,
tpoints: SampleRect, tpoints: SampleRect,
tsize: (i32, i32), tsize: (i32, i32),
bounds: Option<&Rect>, bounds: Option<&Rect>,
) { ) {
if let Some(tex) = buffer.texture.get() { if let Some(tex) = buffer.buffer.texture.get() {
self.base.render_texture( self.base.render_texture(
&tex, &tex,
x, x,
@ -361,8 +362,9 @@ impl Renderer<'_> {
Some(tsize), Some(tsize),
self.base.scale, self.base.scale,
bounds, 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) { if let Some(rect) = Rect::new_sized(x, y, tsize.0, tsize.1) {
let rect = match bounds { let rect = match bounds {
None => rect, None => rect,
@ -409,8 +411,16 @@ impl Renderer<'_> {
self.base.fill_boxes(&title_underline, &uc); self.base.fill_boxes(&title_underline, &uc);
if let Some(title) = floating.title_textures.get(&self.base.scale) { if let Some(title) = floating.title_textures.get(&self.base.scale) {
let (x, y) = self.base.scale_point(x + bw, y + bw); let (x, y) = self.base.scale_point(x + bw, y + bw);
self.base self.base.render_texture(
.render_texture(&title.texture, x, y, None, None, self.base.scale, None); &title.texture,
x,
y,
None,
None,
self.base.scale,
None,
None,
);
} }
let body = Rect::new_sized( let body = Rect::new_sized(
x + bw, x + bw,

View file

@ -1,6 +1,8 @@
use { use {
crate::{ crate::{
gfx_api::{CopyTexture, FillRect, FramebufferRect, GfxApiOpt, GfxTexture, SampleRect}, gfx_api::{
BufferResv, CopyTexture, FillRect, FramebufferRect, GfxApiOpt, GfxTexture, SampleRect,
},
rect::Rect, rect::Rect,
scale::Scale, scale::Scale,
theme::Color, theme::Color,
@ -130,6 +132,7 @@ impl RendererBase<'_> {
tsize: Option<(i32, i32)>, tsize: Option<(i32, i32)>,
tscale: Scale, tscale: Scale,
bounds: Option<&Rect>, bounds: Option<&Rect>,
buffer_resv: Option<Rc<dyn BufferResv>>,
) { ) {
let mut texcoord = tpoints.unwrap_or_else(SampleRect::identity); 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 { self.ops.push(GfxApiOpt::CopyTexture(CopyTexture {
tex: texture.clone(), tex: texture.clone(),
source: texcoord, source: texcoord,
target: FramebufferRect::new( target,
target_x[0] as f32, buffer_resv,
target_y[0] as f32,
target_x[1] as f32,
target_y[1] as f32,
self.transform,
self.fb_width,
self.fb_height,
),
})); }));
} }
} }

View file

@ -408,7 +408,7 @@ impl State {
} }
fn visit_surface(&mut self, node: &Rc<WlSurface>) { fn visit_surface(&mut self, node: &Rc<WlSurface>) {
if let Some(buffer) = node.buffer.get() { if let Some(buffer) = node.buffer.get() {
buffer.handle_gfx_context_change(); buffer.buffer.handle_gfx_context_change();
} }
node.node_visit_children(self); node.node_visit_children(self);
} }
@ -814,6 +814,7 @@ impl State {
size, size,
Scale::from_int(1), Scale::from_int(1),
None, None,
None,
); );
if render_hardware_cursors { if render_hardware_cursors {
for seat in self.globals.lock_seats().values() { for seat in self.globals.lock_seats().values() {

View file

@ -48,6 +48,13 @@ impl DmaBuf {
} }
false 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 _; const DMA_BUF_BASE: u64 = b'b' as _;