1
0
Fork 0
forked from wry/wry

allocator: don't require render usage for bridged buffers

This commit is contained in:
Julian Orth 2024-09-05 11:48:30 +02:00
parent 1bacaa7b02
commit bf65da4c76
15 changed files with 152 additions and 54 deletions

View file

@ -12,8 +12,8 @@ use {
edid::Descriptor, edid::Descriptor,
format::{Format, ARGB8888, XRGB8888}, format::{Format, ARGB8888, XRGB8888},
gfx_api::{ gfx_api::{
AcquireSync, BufferResv, GfxApiOpt, GfxContext, GfxFramebuffer, GfxRenderPass, needs_render_usage, AcquireSync, BufferResv, GfxApiOpt, GfxContext, GfxFramebuffer,
GfxTexture, ReleaseSync, SyncFile, GfxRenderPass, GfxTexture, ReleaseSync, SyncFile,
}, },
ifs::{ ifs::{
wl_output::OutputId, wl_output::OutputId,
@ -46,7 +46,7 @@ use {
ahash::{AHashMap, AHashSet}, ahash::{AHashMap, AHashSet},
arrayvec::ArrayVec, arrayvec::ArrayVec,
bstr::{BString, ByteSlice}, bstr::{BString, ByteSlice},
indexmap::{indexset, IndexSet}, indexmap::{indexset, IndexMap, IndexSet},
isnt::std_1::collections::IsntHashMap2Ext, isnt::std_1::collections::IsntHashMap2Ext,
jay_config::video::GfxApi, jay_config::video::GfxApi,
once_cell::sync::Lazy, once_cell::sync::Lazy,
@ -2853,18 +2853,24 @@ impl MetalBackend {
None => return Err(MetalError::MissingDevFormat(format.name)), None => return Err(MetalError::MissingDevFormat(format.name)),
Some(f) => f, Some(f) => f,
}; };
let possible_modifiers: Vec<_> = dev_gfx_format let possible_modifiers: IndexMap<_, _> = dev_gfx_format
.write_modifiers .write_modifiers
.iter() .iter()
.filter(|m| plane_modifiers.contains(*m)) .filter(|(m, _)| plane_modifiers.contains(*m))
.copied() .map(|(m, v)| (*m, v))
.collect(); .collect();
if possible_modifiers.is_empty() { if possible_modifiers.is_empty() {
log::warn!("Scanout modifiers: {:?}", plane_modifiers); 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)); return Err(MetalError::MissingDevModifier(format.name));
} }
let mut usage = GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT; 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 { if cursor {
usage |= GBM_BO_USE_LINEAR; usage |= GBM_BO_USE_LINEAR;
}; };
@ -2873,7 +2879,7 @@ impl MetalBackend {
width, width,
height, height,
format, format,
&possible_modifiers, possible_modifiers.keys(),
usage, usage,
); );
let dev_bo = match dev_bo { let dev_bo = match dev_bo {
@ -2906,27 +2912,30 @@ impl MetalBackend {
None => return Err(MetalError::MissingRenderFormat(format.name)), None => return Err(MetalError::MissingRenderFormat(format.name)),
Some(f) => f, Some(f) => f,
}; };
let possible_modifiers: Vec<_> = render_gfx_format let possible_modifiers: IndexMap<_, _> = render_gfx_format
.write_modifiers .write_modifiers
.iter() .iter()
.filter(|m| dev_gfx_format.read_modifiers.contains(*m)) .filter(|(m, _)| dev_gfx_format.read_modifiers.contains(*m))
.copied() .map(|(m, v)| (*m, v))
.collect(); .collect();
if possible_modifiers.is_empty() { if possible_modifiers.is_empty() {
log::warn!( log::warn!(
"Render GFX modifiers: {:?}", "Render GFX modifiers: {:?}",
render_gfx_format.write_modifiers render_gfx_format.write_modifiers.keys()
); );
log::warn!("DEV GFX modifiers: {:?}", dev_gfx_format.read_modifiers); log::warn!("DEV GFX modifiers: {:?}", dev_gfx_format.read_modifiers);
return Err(MetalError::MissingRenderModifier(format.name)); return Err(MetalError::MissingRenderModifier(format.name));
} }
usage = GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR; 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( let render_bo = render_ctx.gbm.create_bo(
&self.state.dma_buf_ids, &self.state.dma_buf_ids,
width, width,
height, height,
format, format,
&possible_modifiers, possible_modifiers.keys(),
usage, usage,
); );
let render_bo = match render_bo { let render_bo = match render_bo {

View file

@ -389,7 +389,7 @@ impl XBackend {
width, width,
height, height,
XRGB8888, XRGB8888,
&format.write_modifiers, format.write_modifiers.keys(),
GBM_BO_USE_RENDERING, GBM_BO_USE_RENDERING,
)?; )?;
let dma = bo.dmabuf(); let dma = bo.dmabuf();

View file

@ -15,7 +15,7 @@ use {
video::{dmabuf::DmaBuf, drm::sync_obj::SyncObjCtx, Modifier}, video::{dmabuf::DmaBuf, drm::sync_obj::SyncObjCtx, Modifier},
}, },
ahash::AHashMap, ahash::AHashMap,
indexmap::IndexSet, indexmap::{IndexMap, IndexSet},
jay_config::video::{GfxApi, Transform}, jay_config::video::{GfxApi, Transform},
std::{ std::{
any::Any, any::Any,
@ -570,11 +570,20 @@ pub trait GfxContext: Debug {
fn sync_obj_ctx(&self) -> Option<&Rc<SyncObjCtx>>; fn sync_obj_ctx(&self) -> Option<&Rc<SyncObjCtx>>;
} }
#[derive(Clone, Debug)]
pub struct GfxWriteModifier {
pub needs_render_usage: bool,
}
pub fn needs_render_usage<'a>(mut modifiers: impl Iterator<Item = &'a GfxWriteModifier>) -> bool {
modifiers.any(|m| m.needs_render_usage)
}
#[derive(Debug)] #[derive(Debug)]
pub struct GfxFormat { pub struct GfxFormat {
pub format: &'static Format, pub format: &'static Format,
pub read_modifiers: IndexSet<Modifier>, pub read_modifiers: IndexSet<Modifier>,
pub write_modifiers: IndexSet<Modifier>, pub write_modifiers: IndexMap<Modifier, GfxWriteModifier>,
} }
#[derive(Error)] #[derive(Error)]
@ -594,13 +603,15 @@ impl GfxFormat {
format: self.format, format: self.format,
read_modifiers: self read_modifiers: self
.read_modifiers .read_modifiers
.intersection(&other.write_modifiers) .iter()
.copied() .copied()
.filter(|m| other.write_modifiers.contains_key(m))
.collect(), .collect(),
write_modifiers: self write_modifiers: self
.write_modifiers .write_modifiers
.intersection(&other.read_modifiers) .iter()
.copied() .map(|(m, v)| (*m, v.clone()))
.filter(|(m, _)| other.read_modifiers.contains(m))
.collect(), .collect(),
} }
} }

View file

@ -1,7 +1,7 @@
use { use {
crate::{ crate::{
format::{formats, Format}, format::{formats, Format},
gfx_api::GfxFormat, gfx_api::{GfxFormat, GfxWriteModifier},
gfx_apis::gl::{ gfx_apis::gl::{
egl::{ egl::{
context::EglContext, context::EglContext,
@ -173,13 +173,18 @@ impl EglDisplay {
continue; continue;
} }
let mut read_modifiers = IndexSet::new(); let mut read_modifiers = IndexSet::new();
let mut write_modifiers = IndexSet::new(); let mut write_modifiers = IndexMap::new();
for modifier in format.modifiers.values() { for modifier in format.modifiers.values() {
if modifier.external_only && !supports_external_only { if modifier.external_only && !supports_external_only {
continue; continue;
} }
if !modifier.external_only { if !modifier.external_only {
write_modifiers.insert(modifier.modifier); write_modifiers.insert(
modifier.modifier,
GfxWriteModifier {
needs_render_usage: true,
},
);
} }
read_modifiers.insert(modifier.modifier); read_modifiers.insert(modifier.modifier);
} }

View file

@ -4,7 +4,7 @@ use {
format::{Format, XRGB8888}, format::{Format, XRGB8888},
gfx_api::{ gfx_api::{
AcquireSync, BufferResv, BufferResvUser, GfxApiOpt, GfxFormat, GfxFramebuffer, AcquireSync, BufferResv, BufferResvUser, GfxApiOpt, GfxFormat, GfxFramebuffer,
GfxTexture, ReleaseSync, SyncFile, GfxTexture, GfxWriteModifier, ReleaseSync, SyncFile,
}, },
gfx_apis::vulkan::{ gfx_apis::vulkan::{
allocator::VulkanAllocator, allocator::VulkanAllocator,
@ -158,7 +158,14 @@ impl VulkanDevice {
.modifiers .modifiers
.values() .values()
.filter(|m| m.render_limits.is_some()) .filter(|m| m.render_limits.is_some())
.map(|m| m.modifier) .map(|m| {
(
m.modifier,
GfxWriteModifier {
needs_render_usage: !m.render_needs_bridge,
},
)
})
.collect(), .collect(),
}, },
) )

View file

@ -70,7 +70,7 @@ impl Global for JayCompositorGlobal {
} }
fn version(&self) -> u32 { fn version(&self) -> u32 {
8 9
} }
fn required_caps(&self) -> ClientCaps { fn required_caps(&self) -> ClientCaps {

View file

@ -12,6 +12,7 @@ use {
}; };
pub const FORMATS_SINCE: Version = Version(7); pub const FORMATS_SINCE: Version = Version(7);
pub const WRITE_MODIFIER_2_SINCE: Version = Version(9);
pub struct JayRenderCtx { pub struct JayRenderCtx {
pub id: JayRenderCtxId, pub id: JayRenderCtxId,
@ -30,12 +31,21 @@ impl JayRenderCtx {
self_id: self.id, self_id: self.id,
format: format.format.drm, format: format.format.drm,
}); });
for modifier in &format.write_modifiers { for (modifier, gwm) in &format.write_modifiers {
self.client.event(WriteModifier { if self.version >= WRITE_MODIFIER_2_SINCE {
self_id: self.id, self.client.event(WriteModifier2 {
format: format.format.drm, self_id: self.id,
modifier: *modifier, 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 { for modifier in &format.read_modifiers {
self.client.event(ReadModifier { self.client.event(ReadModifier {

View file

@ -414,10 +414,10 @@ impl JayScreencast {
} }
let mut usage = BO_USE_RENDERING; let mut usage = BO_USE_RENDERING;
let modifiers = match self.linear.get() { 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] vec![LINEAR_MODIFIER]
} }
true if format.write_modifiers.contains(&INVALID_MODIFIER) => { true if format.write_modifiers.contains_key(&INVALID_MODIFIER) => {
usage |= BO_USE_LINEAR; usage |= BO_USE_LINEAR;
vec![INVALID_MODIFIER] vec![INVALID_MODIFIER]
} }
@ -425,7 +425,7 @@ impl JayScreencast {
false if format.write_modifiers.is_empty() => { false if format.write_modifiers.is_empty() => {
return Err(JayScreencastError::XRGB8888Writing) return Err(JayScreencastError::XRGB8888Writing)
} }
false => format.write_modifiers.iter().copied().collect(), false => format.write_modifiers.keys().copied().collect(),
}; };
let buffer = ctx.allocator().create_bo( let buffer = ctx.allocator().create_bo(
&self.client.state.dma_buf_ids, &self.client.state.dma_buf_ids,

View file

@ -4,7 +4,7 @@ use {
format::{Format, ARGB8888, XRGB8888}, format::{Format, ARGB8888, XRGB8888},
gfx_api::{ gfx_api::{
CopyTexture, FillRect, FramebufferRect, GfxApiOpt, GfxContext, GfxError, GfxFormat, CopyTexture, FillRect, FramebufferRect, GfxApiOpt, GfxContext, GfxError, GfxFormat,
GfxFramebuffer, GfxImage, GfxTexture, ResetStatus, SyncFile, GfxFramebuffer, GfxImage, GfxTexture, GfxWriteModifier, ResetStatus, SyncFile,
}, },
rect::Rect, rect::Rect,
theme::Color, theme::Color,
@ -55,7 +55,18 @@ impl TestGfxCtx {
GfxFormat { GfxFormat {
format: f, format: f,
read_modifiers: modifiers.clone(), read_modifiers: modifiers.clone(),
write_modifiers: modifiers.clone(), write_modifiers: modifiers
.iter()
.copied()
.map(|m| {
(
m,
GfxWriteModifier {
needs_render_usage: false,
},
)
})
.collect(),
}, },
); );
} }

View file

@ -323,7 +323,7 @@ fn finish_display_connect(dpy: Rc<PortalDisplayPrelude>) {
con: dpy.con.clone(), con: dpy.con.clone(),
owner: Default::default(), owner: Default::default(),
caps: Default::default(), caps: Default::default(),
version: Version(version.min(7)), version: Version(version.min(9)),
}); });
dpy.con.add_object(jc.clone()); dpy.con.add_object(jc.clone());
dpy.registry.request_bind(name, jc.version.0, jc.deref()); dpy.registry.request_bind(name, jc.version.0, jc.deref());

View file

@ -2,7 +2,7 @@ mod screencast_gui;
use { use {
crate::{ crate::{
allocator::{AllocatorError, BufferObject, BO_USE_RENDERING}, allocator::{AllocatorError, BufferObject, BufferUsage, BO_USE_RENDERING},
dbus::{prelude::Variant, DbusObject, DictEntry, DynamicType, PendingReply}, dbus::{prelude::Variant, DbusObject, DictEntry, DynamicType, PendingReply},
format::{Format, XRGB8888}, format::{Format, XRGB8888},
ifs::jay_screencast::CLIENT_BUFFERS_SINCE, ifs::jay_screencast::CLIENT_BUFFERS_SINCE,
@ -204,7 +204,7 @@ impl PwClientNodeOwner for StartingScreencast {
} }
let ptl_format = PwClientNodePortSupportedFormat { let ptl_format = PwClientNodePortSupportedFormat {
format: format.format, format: format.format,
modifiers: format.write_modifiers.iter().copied().collect(), modifiers: format.write_modifiers.keys().copied().collect(),
}; };
supported_formats.formats.push(ptl_format); supported_formats.formats.push(ptl_format);
} }
@ -380,13 +380,28 @@ impl StartedScreencast {
let Some(ctx) = self.dpy.render_ctx.get() else { let Some(ctx) = self.dpy.render_ctx.get() else {
return Err(BufferAllocationError::NoRenderContext); 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( let buffer = ctx.ctx.ctx.allocator().create_bo(
&self.dpy.state.dma_buf_ids, &self.dpy.state.dma_buf_ids,
width, width,
height, height,
format, format,
modifiers, modifiers,
BO_USE_RENDERING, usage,
)?; )?;
Ok(buffer) Ok(buffer)
} }

View file

@ -1,11 +1,11 @@
use { use {
crate::{ crate::{
allocator::{BufferObject, BO_USE_RENDERING}, allocator::{BufferObject, BufferUsage, BO_USE_RENDERING},
async_engine::{Phase, SpawnedFuture}, async_engine::{Phase, SpawnedFuture},
cursor::KnownCursor, cursor::KnownCursor,
fixed::Fixed, fixed::Fixed,
format::ARGB8888, format::ARGB8888,
gfx_api::{AcquireSync, GfxContext, GfxFramebuffer, ReleaseSync}, gfx_api::{needs_render_usage, AcquireSync, GfxContext, GfxFramebuffer, ReleaseSync},
ifs::zwlr_layer_shell_v1::OVERLAY, ifs::zwlr_layer_shell_v1::OVERLAY,
portal::ptl_display::{PortalDisplay, PortalOutput, PortalSeat}, portal::ptl_display::{PortalDisplay, PortalOutput, PortalSeat},
renderer::renderer_base::RendererBase, renderer::renderer_base::RendererBase,
@ -723,7 +723,11 @@ impl WindowData {
log::error!("Render context cannot render to ARGB8888 format"); log::error!("Render context cannot render to ARGB8888 format");
return; 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 { for _ in 0..NUM_BUFFERS {
let bo = match ctx.ctx.ctx.allocator().create_bo( let bo = match ctx.ctx.ctx.allocator().create_bo(
&self.dpy.state.dma_buf_ids, &self.dpy.state.dma_buf_ids,
@ -731,7 +735,7 @@ impl WindowData {
height, height,
ARGB8888, ARGB8888,
&modifiers, &modifiers,
BO_USE_RENDERING, usage,
) { ) {
Ok(b) => b, Ok(b) => b,
Err(e) => { Err(e) => {

View file

@ -1,12 +1,13 @@
use { use {
crate::{ crate::{
allocator::{AllocatorError, BufferObject, BO_USE_RENDERING}, allocator::{AllocatorError, BufferObject, BufferUsage, BO_USE_RENDERING},
format::XRGB8888, format::XRGB8888,
gfx_api::GfxError, gfx_api::{needs_render_usage, GfxError},
scale::Scale, scale::Scale,
state::State, state::State,
video::drm::DrmError, video::drm::DrmError,
}, },
indexmap::IndexMap,
jay_config::video::Transform, jay_config::video::Transform,
std::{ops::Deref, rc::Rc}, std::{ops::Deref, rc::Rc},
thiserror::Error, thiserror::Error,
@ -49,17 +50,22 @@ pub fn take_screenshot(
return Err(ScreenshooterError::EmptyDisplay); return Err(ScreenshooterError::EmptyDisplay);
} }
let formats = ctx.formats(); 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), None => return Err(ScreenshooterError::XRGB8888),
Some(f) => f Some(f) => f
.write_modifiers .write_modifiers
.intersection(&f.read_modifiers) .iter()
.copied() .filter(|(m, _)| f.read_modifiers.contains(*m))
.collect(), .collect(),
}; };
if modifiers.is_empty() { if modifiers.is_empty() {
return Err(ScreenshooterError::Modifiers); 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 allocator = ctx.allocator();
let bo = allocator.create_bo( let bo = allocator.create_bo(
&state.dma_buf_ids, &state.dma_buf_ids,
@ -67,7 +73,7 @@ pub fn take_screenshot(
extents.height(), extents.height(),
XRGB8888, XRGB8888,
&modifiers, &modifiers,
BO_USE_RENDERING, usage,
)?; )?;
let fb = ctx.clone().dmabuf_fb(bo.dmabuf())?; let fb = ctx.clone().dmabuf_fb(bo.dmabuf())?;
fb.render_node( fb.render_node(

View file

@ -1,10 +1,11 @@
use { use {
crate::{ crate::{
format::formats, format::formats,
gfx_api::GfxFormat, gfx_api::{GfxFormat, GfxWriteModifier},
ifs::jay_render_ctx::FORMATS_SINCE, ifs::jay_render_ctx::FORMATS_SINCE,
object::Version, object::Version,
utils::clonecell::CloneCell, utils::clonecell::CloneCell,
video::Modifier,
wire::{jay_render_ctx::*, JayRenderCtxId}, wire::{jay_render_ctx::*, JayRenderCtxId},
wl_usr::{usr_object::UsrObject, UsrCon}, 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 { impl JayRenderCtxEventHandler for UsrJayRenderCtx {
type Error = Infallible; type Error = Infallible;
@ -57,9 +68,7 @@ impl JayRenderCtxEventHandler for UsrJayRenderCtx {
} }
fn write_modifier(&self, ev: WriteModifier, _slf: &Rc<Self>) -> Result<(), Self::Error> { fn write_modifier(&self, ev: WriteModifier, _slf: &Rc<Self>) -> Result<(), Self::Error> {
if let Some(format) = self.formats.borrow_mut().get_mut(&ev.format) { self.add_write_modifier(ev.format, ev.modifier, true);
format.write_modifiers.insert(ev.modifier);
}
Ok(()) Ok(())
} }
@ -76,6 +85,11 @@ impl JayRenderCtxEventHandler for UsrJayRenderCtx {
} }
Ok(()) Ok(())
} }
fn write_modifier2(&self, ev: WriteModifier2, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.add_write_modifier(ev.format, ev.modifier, ev.needs_render_usage != 0);
Ok(())
}
} }
usr_object_base! { usr_object_base! {

View file

@ -27,3 +27,9 @@ event write_modifier (since = 7) {
event format (since = 7) { event format (since = 7) {
format: u32, format: u32,
} }
event write_modifier2 (since = 9) {
format: u32,
modifier: pod(u64),
needs_render_usage: u32,
}