From bf65da4c76fa28149b572c622dad30542657b489 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Thu, 5 Sep 2024 11:48:30 +0200 Subject: [PATCH] allocator: don't require render usage for bridged buffers --- src/backends/metal/video.rs | 35 +++++++++++++++--------- src/backends/x.rs | 2 +- src/gfx_api.rs | 21 ++++++++++---- src/gfx_apis/gl/egl/display.rs | 11 ++++++-- src/gfx_apis/vulkan/renderer.rs | 11 ++++++-- src/ifs/jay_compositor.rs | 2 +- src/ifs/jay_render_ctx.rs | 22 +++++++++++---- src/ifs/jay_screencast.rs | 6 ++-- src/it/test_gfx_api.rs | 15 ++++++++-- src/portal/ptl_display.rs | 2 +- src/portal/ptl_screencast.rs | 21 ++++++++++++-- src/portal/ptr_gui.rs | 12 +++++--- src/screenshoter.rs | 18 ++++++++---- src/wl_usr/usr_ifs/usr_jay_render_ctx.rs | 22 ++++++++++++--- wire/jay_render_ctx.txt | 6 ++++ 15 files changed, 152 insertions(+), 54 deletions(-) diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index 25d49337..51c36192 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -12,8 +12,8 @@ use { edid::Descriptor, format::{Format, ARGB8888, XRGB8888}, gfx_api::{ - AcquireSync, BufferResv, GfxApiOpt, GfxContext, GfxFramebuffer, GfxRenderPass, - GfxTexture, ReleaseSync, SyncFile, + needs_render_usage, AcquireSync, BufferResv, GfxApiOpt, GfxContext, GfxFramebuffer, + GfxRenderPass, GfxTexture, ReleaseSync, SyncFile, }, ifs::{ wl_output::OutputId, @@ -46,7 +46,7 @@ use { ahash::{AHashMap, AHashSet}, arrayvec::ArrayVec, bstr::{BString, ByteSlice}, - indexmap::{indexset, IndexSet}, + indexmap::{indexset, IndexMap, IndexSet}, isnt::std_1::collections::IsntHashMap2Ext, jay_config::video::GfxApi, once_cell::sync::Lazy, @@ -2853,18 +2853,24 @@ impl MetalBackend { None => return Err(MetalError::MissingDevFormat(format.name)), Some(f) => f, }; - let possible_modifiers: Vec<_> = dev_gfx_format + let possible_modifiers: IndexMap<_, _> = dev_gfx_format .write_modifiers .iter() - .filter(|m| plane_modifiers.contains(*m)) - .copied() + .filter(|(m, _)| plane_modifiers.contains(*m)) + .map(|(m, v)| (*m, v)) .collect(); if possible_modifiers.is_empty() { log::warn!("Scanout modifiers: {:?}", plane_modifiers); - log::warn!("DEV GFX modifiers: {:?}", dev_gfx_format.write_modifiers); + log::warn!( + "DEV GFX modifiers: {:?}", + dev_gfx_format.write_modifiers.keys() + ); return Err(MetalError::MissingDevModifier(format.name)); } let mut usage = GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT; + if !needs_render_usage(possible_modifiers.values().copied()) { + usage &= !GBM_BO_USE_RENDERING; + } if cursor { usage |= GBM_BO_USE_LINEAR; }; @@ -2873,7 +2879,7 @@ impl MetalBackend { width, height, format, - &possible_modifiers, + possible_modifiers.keys(), usage, ); let dev_bo = match dev_bo { @@ -2906,27 +2912,30 @@ impl MetalBackend { None => return Err(MetalError::MissingRenderFormat(format.name)), Some(f) => f, }; - let possible_modifiers: Vec<_> = render_gfx_format + let possible_modifiers: IndexMap<_, _> = render_gfx_format .write_modifiers .iter() - .filter(|m| dev_gfx_format.read_modifiers.contains(*m)) - .copied() + .filter(|(m, _)| dev_gfx_format.read_modifiers.contains(*m)) + .map(|(m, v)| (*m, v)) .collect(); if possible_modifiers.is_empty() { log::warn!( "Render GFX modifiers: {:?}", - render_gfx_format.write_modifiers + render_gfx_format.write_modifiers.keys() ); log::warn!("DEV GFX modifiers: {:?}", dev_gfx_format.read_modifiers); return Err(MetalError::MissingRenderModifier(format.name)); } usage = GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR; + if !needs_render_usage(possible_modifiers.values().copied()) { + usage &= !GBM_BO_USE_RENDERING; + } let render_bo = render_ctx.gbm.create_bo( &self.state.dma_buf_ids, width, height, format, - &possible_modifiers, + possible_modifiers.keys(), usage, ); let render_bo = match render_bo { diff --git a/src/backends/x.rs b/src/backends/x.rs index 9b1b54ed..0b80f5c7 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -389,7 +389,7 @@ impl XBackend { width, height, XRGB8888, - &format.write_modifiers, + format.write_modifiers.keys(), GBM_BO_USE_RENDERING, )?; let dma = bo.dmabuf(); diff --git a/src/gfx_api.rs b/src/gfx_api.rs index 2da1d71d..d8100264 100644 --- a/src/gfx_api.rs +++ b/src/gfx_api.rs @@ -15,7 +15,7 @@ use { video::{dmabuf::DmaBuf, drm::sync_obj::SyncObjCtx, Modifier}, }, ahash::AHashMap, - indexmap::IndexSet, + indexmap::{IndexMap, IndexSet}, jay_config::video::{GfxApi, Transform}, std::{ any::Any, @@ -570,11 +570,20 @@ pub trait GfxContext: Debug { fn sync_obj_ctx(&self) -> Option<&Rc>; } +#[derive(Clone, Debug)] +pub struct GfxWriteModifier { + pub needs_render_usage: bool, +} + +pub fn needs_render_usage<'a>(mut modifiers: impl Iterator) -> bool { + modifiers.any(|m| m.needs_render_usage) +} + #[derive(Debug)] pub struct GfxFormat { pub format: &'static Format, pub read_modifiers: IndexSet, - pub write_modifiers: IndexSet, + pub write_modifiers: IndexMap, } #[derive(Error)] @@ -594,13 +603,15 @@ impl GfxFormat { format: self.format, read_modifiers: self .read_modifiers - .intersection(&other.write_modifiers) + .iter() .copied() + .filter(|m| other.write_modifiers.contains_key(m)) .collect(), write_modifiers: self .write_modifiers - .intersection(&other.read_modifiers) - .copied() + .iter() + .map(|(m, v)| (*m, v.clone())) + .filter(|(m, _)| other.read_modifiers.contains(m)) .collect(), } } diff --git a/src/gfx_apis/gl/egl/display.rs b/src/gfx_apis/gl/egl/display.rs index 80e4a91c..7d139c41 100644 --- a/src/gfx_apis/gl/egl/display.rs +++ b/src/gfx_apis/gl/egl/display.rs @@ -1,7 +1,7 @@ use { crate::{ format::{formats, Format}, - gfx_api::GfxFormat, + gfx_api::{GfxFormat, GfxWriteModifier}, gfx_apis::gl::{ egl::{ context::EglContext, @@ -173,13 +173,18 @@ impl EglDisplay { continue; } let mut read_modifiers = IndexSet::new(); - let mut write_modifiers = IndexSet::new(); + let mut write_modifiers = IndexMap::new(); for modifier in format.modifiers.values() { if modifier.external_only && !supports_external_only { continue; } if !modifier.external_only { - write_modifiers.insert(modifier.modifier); + write_modifiers.insert( + modifier.modifier, + GfxWriteModifier { + needs_render_usage: true, + }, + ); } read_modifiers.insert(modifier.modifier); } diff --git a/src/gfx_apis/vulkan/renderer.rs b/src/gfx_apis/vulkan/renderer.rs index 834b5d26..d884d76f 100644 --- a/src/gfx_apis/vulkan/renderer.rs +++ b/src/gfx_apis/vulkan/renderer.rs @@ -4,7 +4,7 @@ use { format::{Format, XRGB8888}, gfx_api::{ AcquireSync, BufferResv, BufferResvUser, GfxApiOpt, GfxFormat, GfxFramebuffer, - GfxTexture, ReleaseSync, SyncFile, + GfxTexture, GfxWriteModifier, ReleaseSync, SyncFile, }, gfx_apis::vulkan::{ allocator::VulkanAllocator, @@ -158,7 +158,14 @@ impl VulkanDevice { .modifiers .values() .filter(|m| m.render_limits.is_some()) - .map(|m| m.modifier) + .map(|m| { + ( + m.modifier, + GfxWriteModifier { + needs_render_usage: !m.render_needs_bridge, + }, + ) + }) .collect(), }, ) diff --git a/src/ifs/jay_compositor.rs b/src/ifs/jay_compositor.rs index 8b8fa725..401852ec 100644 --- a/src/ifs/jay_compositor.rs +++ b/src/ifs/jay_compositor.rs @@ -70,7 +70,7 @@ impl Global for JayCompositorGlobal { } fn version(&self) -> u32 { - 8 + 9 } fn required_caps(&self) -> ClientCaps { diff --git a/src/ifs/jay_render_ctx.rs b/src/ifs/jay_render_ctx.rs index ee7152d6..147c13fb 100644 --- a/src/ifs/jay_render_ctx.rs +++ b/src/ifs/jay_render_ctx.rs @@ -12,6 +12,7 @@ use { }; pub const FORMATS_SINCE: Version = Version(7); +pub const WRITE_MODIFIER_2_SINCE: Version = Version(9); pub struct JayRenderCtx { pub id: JayRenderCtxId, @@ -30,12 +31,21 @@ impl JayRenderCtx { self_id: self.id, format: format.format.drm, }); - for modifier in &format.write_modifiers { - self.client.event(WriteModifier { - self_id: self.id, - format: format.format.drm, - modifier: *modifier, - }); + for (modifier, gwm) in &format.write_modifiers { + if self.version >= WRITE_MODIFIER_2_SINCE { + self.client.event(WriteModifier2 { + self_id: self.id, + format: format.format.drm, + modifier: *modifier, + needs_render_usage: gwm.needs_render_usage as _, + }); + } else { + self.client.event(WriteModifier { + self_id: self.id, + format: format.format.drm, + modifier: *modifier, + }); + } } for modifier in &format.read_modifiers { self.client.event(ReadModifier { diff --git a/src/ifs/jay_screencast.rs b/src/ifs/jay_screencast.rs index 9e43f03f..e559876f 100644 --- a/src/ifs/jay_screencast.rs +++ b/src/ifs/jay_screencast.rs @@ -414,10 +414,10 @@ impl JayScreencast { } let mut usage = BO_USE_RENDERING; let modifiers = match self.linear.get() { - true if format.write_modifiers.contains(&LINEAR_MODIFIER) => { + true if format.write_modifiers.contains_key(&LINEAR_MODIFIER) => { vec![LINEAR_MODIFIER] } - true if format.write_modifiers.contains(&INVALID_MODIFIER) => { + true if format.write_modifiers.contains_key(&INVALID_MODIFIER) => { usage |= BO_USE_LINEAR; vec![INVALID_MODIFIER] } @@ -425,7 +425,7 @@ impl JayScreencast { false if format.write_modifiers.is_empty() => { return Err(JayScreencastError::XRGB8888Writing) } - false => format.write_modifiers.iter().copied().collect(), + false => format.write_modifiers.keys().copied().collect(), }; let buffer = ctx.allocator().create_bo( &self.client.state.dma_buf_ids, diff --git a/src/it/test_gfx_api.rs b/src/it/test_gfx_api.rs index 032fa402..19f55018 100644 --- a/src/it/test_gfx_api.rs +++ b/src/it/test_gfx_api.rs @@ -4,7 +4,7 @@ use { format::{Format, ARGB8888, XRGB8888}, gfx_api::{ CopyTexture, FillRect, FramebufferRect, GfxApiOpt, GfxContext, GfxError, GfxFormat, - GfxFramebuffer, GfxImage, GfxTexture, ResetStatus, SyncFile, + GfxFramebuffer, GfxImage, GfxTexture, GfxWriteModifier, ResetStatus, SyncFile, }, rect::Rect, theme::Color, @@ -55,7 +55,18 @@ impl TestGfxCtx { GfxFormat { format: f, read_modifiers: modifiers.clone(), - write_modifiers: modifiers.clone(), + write_modifiers: modifiers + .iter() + .copied() + .map(|m| { + ( + m, + GfxWriteModifier { + needs_render_usage: false, + }, + ) + }) + .collect(), }, ); } diff --git a/src/portal/ptl_display.rs b/src/portal/ptl_display.rs index 71103501..5f555a6e 100644 --- a/src/portal/ptl_display.rs +++ b/src/portal/ptl_display.rs @@ -323,7 +323,7 @@ fn finish_display_connect(dpy: Rc) { con: dpy.con.clone(), owner: Default::default(), caps: Default::default(), - version: Version(version.min(7)), + version: Version(version.min(9)), }); dpy.con.add_object(jc.clone()); dpy.registry.request_bind(name, jc.version.0, jc.deref()); diff --git a/src/portal/ptl_screencast.rs b/src/portal/ptl_screencast.rs index 60c40f52..886e7812 100644 --- a/src/portal/ptl_screencast.rs +++ b/src/portal/ptl_screencast.rs @@ -2,7 +2,7 @@ mod screencast_gui; use { crate::{ - allocator::{AllocatorError, BufferObject, BO_USE_RENDERING}, + allocator::{AllocatorError, BufferObject, BufferUsage, BO_USE_RENDERING}, dbus::{prelude::Variant, DbusObject, DictEntry, DynamicType, PendingReply}, format::{Format, XRGB8888}, ifs::jay_screencast::CLIENT_BUFFERS_SINCE, @@ -204,7 +204,7 @@ impl PwClientNodeOwner for StartingScreencast { } let ptl_format = PwClientNodePortSupportedFormat { format: format.format, - modifiers: format.write_modifiers.iter().copied().collect(), + modifiers: format.write_modifiers.keys().copied().collect(), }; supported_formats.formats.push(ptl_format); } @@ -380,13 +380,28 @@ impl StartedScreencast { let Some(ctx) = self.dpy.render_ctx.get() else { return Err(BufferAllocationError::NoRenderContext); }; + let mut usage = BO_USE_RENDERING; + if let Some(sf) = &ctx.server_formats { + if let Some(format) = sf.get(&format.drm) { + let no_render_usage = modifiers.iter().all(|m| { + format + .write_modifiers + .get(m) + .map(|w| !w.needs_render_usage) + .unwrap_or(false) + }); + if no_render_usage { + usage = BufferUsage::none(); + } + } + } let buffer = ctx.ctx.ctx.allocator().create_bo( &self.dpy.state.dma_buf_ids, width, height, format, modifiers, - BO_USE_RENDERING, + usage, )?; Ok(buffer) } diff --git a/src/portal/ptr_gui.rs b/src/portal/ptr_gui.rs index fa06fcab..5926b11f 100644 --- a/src/portal/ptr_gui.rs +++ b/src/portal/ptr_gui.rs @@ -1,11 +1,11 @@ use { crate::{ - allocator::{BufferObject, BO_USE_RENDERING}, + allocator::{BufferObject, BufferUsage, BO_USE_RENDERING}, async_engine::{Phase, SpawnedFuture}, cursor::KnownCursor, fixed::Fixed, format::ARGB8888, - gfx_api::{AcquireSync, GfxContext, GfxFramebuffer, ReleaseSync}, + gfx_api::{needs_render_usage, AcquireSync, GfxContext, GfxFramebuffer, ReleaseSync}, ifs::zwlr_layer_shell_v1::OVERLAY, portal::ptl_display::{PortalDisplay, PortalOutput, PortalSeat}, renderer::renderer_base::RendererBase, @@ -723,7 +723,11 @@ impl WindowData { log::error!("Render context cannot render to ARGB8888 format"); return; } - let modifiers: Vec<_> = format.write_modifiers.iter().copied().collect(); + let modifiers: Vec<_> = format.write_modifiers.keys().copied().collect(); + let mut usage = BO_USE_RENDERING; + if !needs_render_usage(format.write_modifiers.values()) { + usage = BufferUsage::none(); + } for _ in 0..NUM_BUFFERS { let bo = match ctx.ctx.ctx.allocator().create_bo( &self.dpy.state.dma_buf_ids, @@ -731,7 +735,7 @@ impl WindowData { height, ARGB8888, &modifiers, - BO_USE_RENDERING, + usage, ) { Ok(b) => b, Err(e) => { diff --git a/src/screenshoter.rs b/src/screenshoter.rs index f03ed088..4fb7221e 100644 --- a/src/screenshoter.rs +++ b/src/screenshoter.rs @@ -1,12 +1,13 @@ use { crate::{ - allocator::{AllocatorError, BufferObject, BO_USE_RENDERING}, + allocator::{AllocatorError, BufferObject, BufferUsage, BO_USE_RENDERING}, format::XRGB8888, - gfx_api::GfxError, + gfx_api::{needs_render_usage, GfxError}, scale::Scale, state::State, video::drm::DrmError, }, + indexmap::IndexMap, jay_config::video::Transform, std::{ops::Deref, rc::Rc}, thiserror::Error, @@ -49,17 +50,22 @@ pub fn take_screenshot( return Err(ScreenshooterError::EmptyDisplay); } let formats = ctx.formats(); - let modifiers: Vec<_> = match formats.get(&XRGB8888.drm) { + let modifiers: IndexMap<_, _> = match formats.get(&XRGB8888.drm) { None => return Err(ScreenshooterError::XRGB8888), Some(f) => f .write_modifiers - .intersection(&f.read_modifiers) - .copied() + .iter() + .filter(|(m, _)| f.read_modifiers.contains(*m)) .collect(), }; if modifiers.is_empty() { return Err(ScreenshooterError::Modifiers); } + let mut usage = BO_USE_RENDERING; + if !needs_render_usage(modifiers.values().copied()) { + usage = BufferUsage::none(); + } + let modifiers: Vec<_> = modifiers.keys().copied().copied().collect(); let allocator = ctx.allocator(); let bo = allocator.create_bo( &state.dma_buf_ids, @@ -67,7 +73,7 @@ pub fn take_screenshot( extents.height(), XRGB8888, &modifiers, - BO_USE_RENDERING, + usage, )?; let fb = ctx.clone().dmabuf_fb(bo.dmabuf())?; fb.render_node( diff --git a/src/wl_usr/usr_ifs/usr_jay_render_ctx.rs b/src/wl_usr/usr_ifs/usr_jay_render_ctx.rs index 88f5bc48..db3dcb89 100644 --- a/src/wl_usr/usr_ifs/usr_jay_render_ctx.rs +++ b/src/wl_usr/usr_ifs/usr_jay_render_ctx.rs @@ -1,10 +1,11 @@ use { crate::{ format::formats, - gfx_api::GfxFormat, + gfx_api::{GfxFormat, GfxWriteModifier}, ifs::jay_render_ctx::FORMATS_SINCE, object::Version, utils::clonecell::CloneCell, + video::Modifier, wire::{jay_render_ctx::*, JayRenderCtxId}, wl_usr::{usr_object::UsrObject, UsrCon}, }, @@ -29,6 +30,16 @@ pub trait UsrJayRenderCtxOwner { } } +impl UsrJayRenderCtx { + fn add_write_modifier(&self, format: u32, modifier: Modifier, needs_render_usage: bool) { + if let Some(format) = self.formats.borrow_mut().get_mut(&format) { + format + .write_modifiers + .insert(modifier, GfxWriteModifier { needs_render_usage }); + } + } +} + impl JayRenderCtxEventHandler for UsrJayRenderCtx { type Error = Infallible; @@ -57,9 +68,7 @@ impl JayRenderCtxEventHandler for UsrJayRenderCtx { } fn write_modifier(&self, ev: WriteModifier, _slf: &Rc) -> Result<(), Self::Error> { - if let Some(format) = self.formats.borrow_mut().get_mut(&ev.format) { - format.write_modifiers.insert(ev.modifier); - } + self.add_write_modifier(ev.format, ev.modifier, true); Ok(()) } @@ -76,6 +85,11 @@ impl JayRenderCtxEventHandler for UsrJayRenderCtx { } Ok(()) } + + fn write_modifier2(&self, ev: WriteModifier2, _slf: &Rc) -> Result<(), Self::Error> { + self.add_write_modifier(ev.format, ev.modifier, ev.needs_render_usage != 0); + Ok(()) + } } usr_object_base! { diff --git a/wire/jay_render_ctx.txt b/wire/jay_render_ctx.txt index b0cacd85..1f24d615 100644 --- a/wire/jay_render_ctx.txt +++ b/wire/jay_render_ctx.txt @@ -27,3 +27,9 @@ event write_modifier (since = 7) { event format (since = 7) { format: u32, } + +event write_modifier2 (since = 9) { + format: u32, + modifier: pod(u64), + needs_render_usage: u32, +}