feat(wayland): broken buffer usage code
This commit is contained in:
@@ -1,58 +1,59 @@
|
|||||||
use std::sync::{Arc, atomic::AtomicBool};
|
use crate::wayland::Message;
|
||||||
|
|
||||||
use crate::wayland::dmabuf::buffer_backing::DmabufBacking;
|
use crate::wayland::dmabuf::buffer_backing::DmabufBacking;
|
||||||
use crate::{
|
use crate::wayland::{MessageSink, core::shm_buffer_backing::ShmBufferBacking, util::ClientExt};
|
||||||
core::registry::Registry,
|
|
||||||
wayland::{MessageSink, core::shm_buffer_backing::ShmBufferBacking, util::ClientExt},
|
|
||||||
};
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
asset::{Assets, Handle},
|
asset::{Assets, Handle},
|
||||||
image::Image,
|
image::Image,
|
||||||
};
|
};
|
||||||
use bevy_dmabuf::import::ImportedDmatexs;
|
use bevy_dmabuf::import::ImportedDmatexs;
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
|
use std::sync::{Arc, Weak};
|
||||||
pub use waynest::server::protocol::core::wayland::wl_buffer::*;
|
pub use waynest::server::protocol::core::wayland::wl_buffer::*;
|
||||||
use waynest::{
|
use waynest::{
|
||||||
server::{Client, Dispatcher, Result},
|
server::{Client, Dispatcher, Result},
|
||||||
wire::ObjectId,
|
wire::ObjectId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static WL_BUFFER_REGISTRY: Registry<Buffer> = Registry::new();
|
#[derive(Debug)]
|
||||||
|
pub struct BufferUsage {
|
||||||
|
pub buffer: Weak<Buffer>,
|
||||||
|
message_sink: MessageSink,
|
||||||
|
}
|
||||||
|
impl BufferUsage {
|
||||||
|
pub fn new(client: &Client, buffer: &Arc<Buffer>) -> Arc<Self> {
|
||||||
|
Arc::new(Self {
|
||||||
|
buffer: Arc::downgrade(buffer),
|
||||||
|
message_sink: client.message_sink(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Drop for BufferUsage {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(buffer) = self.buffer.upgrade() {
|
||||||
|
self.message_sink
|
||||||
|
.send(Message::ReleaseBuffer(buffer))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum BufferBacking {
|
pub enum BufferBacking {
|
||||||
Shm(ShmBufferBacking),
|
Shm(ShmBufferBacking),
|
||||||
Dmabuf(DmabufBacking),
|
Dmabuf(DmabufBacking),
|
||||||
}
|
}
|
||||||
impl BufferBacking {
|
impl BufferBacking {}
|
||||||
// Returns true if the buffer can be released immediately after texture update
|
|
||||||
pub fn can_release_after_update(&self) -> bool {
|
|
||||||
matches!(self, BufferBacking::Shm(_))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Dispatcher)]
|
#[derive(Debug, Dispatcher)]
|
||||||
pub struct Buffer {
|
pub struct Buffer {
|
||||||
pub id: ObjectId,
|
pub id: ObjectId,
|
||||||
backing: BufferBacking,
|
backing: BufferBacking,
|
||||||
pub message_sink: MessageSink,
|
|
||||||
pub rendered: AtomicBool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Buffer {
|
impl Buffer {
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
#[tracing::instrument(level = "debug", skip_all)]
|
||||||
pub fn new(client: &mut Client, id: ObjectId, backing: BufferBacking) -> Arc<Self> {
|
pub fn new(client: &mut Client, id: ObjectId, backing: BufferBacking) -> Arc<Self> {
|
||||||
let buffer = client.insert(
|
client.insert(id, Self { id, backing })
|
||||||
id,
|
|
||||||
Self {
|
|
||||||
id,
|
|
||||||
backing,
|
|
||||||
message_sink: client.message_sink(),
|
|
||||||
rendered: AtomicBool::new(false),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
WL_BUFFER_REGISTRY.add_raw(&buffer);
|
|
||||||
buffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the tex if it was updated
|
/// Returns the tex if it was updated
|
||||||
@@ -69,10 +70,6 @@ impl Buffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_release_after_update(&self) -> bool {
|
|
||||||
self.backing.can_release_after_update()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_transparent(&self) -> bool {
|
pub fn is_transparent(&self) -> bool {
|
||||||
match &self.backing {
|
match &self.backing {
|
||||||
BufferBacking::Shm(backing) => backing.is_transparent(),
|
BufferBacking::Shm(backing) => backing.is_transparent(),
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use crate::wayland::{RENDER_DEVICE, vulkano_data::VULKANO_CONTEXT};
|
|
||||||
|
|
||||||
use super::shm_pool::ShmPool;
|
use super::shm_pool::ShmPool;
|
||||||
|
use crate::wayland::{RENDER_DEVICE, vulkano_data::VULKANO_CONTEXT};
|
||||||
use bevy::{
|
use bevy::{
|
||||||
asset::{Assets, Handle},
|
asset::{Assets, Handle},
|
||||||
image::Image as BevyImage,
|
image::Image as BevyImage,
|
||||||
@@ -159,6 +158,7 @@ impl ShmBufferBacking {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let imported_texture = import_texture(bevy_render_dev, dmatex, DropCallback(None)).unwrap();
|
let imported_texture = import_texture(bevy_render_dev, dmatex, DropCallback(None)).unwrap();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
pool,
|
pool,
|
||||||
offset,
|
offset,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use crate::{
|
|||||||
nodes::{drawable::model::ModelPart, items::panel::Geometry},
|
nodes::{drawable::model::ModelPart, items::panel::Geometry},
|
||||||
wayland::{
|
wayland::{
|
||||||
Message, MessageSink,
|
Message, MessageSink,
|
||||||
|
core::buffer::BufferUsage,
|
||||||
util::{ClientExt, DoubleBuffer},
|
util::{ClientExt, DoubleBuffer},
|
||||||
xdg::{popup::Popup, toplevel::Toplevel},
|
xdg::{popup::Popup, toplevel::Toplevel},
|
||||||
},
|
},
|
||||||
@@ -17,7 +18,7 @@ use bevy::{
|
|||||||
use bevy_dmabuf::import::ImportedDmatexs;
|
use bevy_dmabuf::import::ImportedDmatexs;
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::sync::{Arc, OnceLock, atomic::Ordering};
|
use std::sync::{Arc, OnceLock};
|
||||||
use waynest::{
|
use waynest::{
|
||||||
server::{
|
server::{
|
||||||
Client, Dispatcher, Result,
|
Client, Dispatcher, Result,
|
||||||
@@ -34,9 +35,15 @@ pub enum SurfaceRole {
|
|||||||
XDGPopup(Arc<Popup>),
|
XDGPopup(Arc<Popup>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct BufferState {
|
||||||
|
pub buffer: Arc<Buffer>,
|
||||||
|
pub usage: Arc<BufferUsage>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SurfaceState {
|
pub struct SurfaceState {
|
||||||
pub buffer: Option<Arc<Buffer>>,
|
pub buffer: Option<BufferState>,
|
||||||
pub density: f32,
|
pub density: f32,
|
||||||
pub geometry: Option<Geometry>,
|
pub geometry: Option<Geometry>,
|
||||||
pub min_size: Option<Vector2<u32>>,
|
pub min_size: Option<Vector2<u32>>,
|
||||||
@@ -121,10 +128,6 @@ impl Surface {
|
|||||||
images: &mut Assets<Image>,
|
images: &mut Assets<Image>,
|
||||||
) {
|
) {
|
||||||
let state_lock = self.state.lock();
|
let state_lock = self.state.lock();
|
||||||
if state_lock.current().clean_lock.get().is_some() {
|
|
||||||
// then we don't need to reupload the texture
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let Some(buffer) = state_lock.current().buffer.clone() else {
|
let Some(buffer) = state_lock.current().buffer.clone() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -145,11 +148,10 @@ impl Surface {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(new_tex) = buffer.update_tex(dmatexes, images) {
|
if let Some(new_tex) = buffer.buffer.update_tex(dmatexes, images) {
|
||||||
buffer.rendered.store(true, Ordering::Relaxed);
|
|
||||||
let material = materials.get_mut(material).unwrap();
|
let material = materials.get_mut(material).unwrap();
|
||||||
material.base_color_texture.replace(new_tex);
|
material.base_color_texture.replace(new_tex);
|
||||||
material.alpha_mode = if buffer.is_transparent() {
|
material.alpha_mode = if buffer.buffer.is_transparent() {
|
||||||
AlphaMode::Premultiplied
|
AlphaMode::Premultiplied
|
||||||
} else {
|
} else {
|
||||||
AlphaMode::Opaque
|
AlphaMode::Opaque
|
||||||
@@ -177,11 +179,7 @@ impl Surface {
|
|||||||
}
|
}
|
||||||
self.pending_material_applications.clear();
|
self.pending_material_applications.clear();
|
||||||
}
|
}
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
#[tracing::instrument("debug", skip_all)]
|
||||||
fn mark_dirty(&self) {
|
|
||||||
self.state.lock().pending.clean_lock = Default::default();
|
|
||||||
}
|
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
|
||||||
pub fn current_state(&self) -> SurfaceState {
|
pub fn current_state(&self) -> SurfaceState {
|
||||||
self.state.lock().current().clone()
|
self.state.lock().current().clone()
|
||||||
}
|
}
|
||||||
@@ -231,7 +229,13 @@ impl WlSurface for Surface {
|
|||||||
_x: i32,
|
_x: i32,
|
||||||
_y: i32,
|
_y: i32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.state.lock().pending.buffer = buffer.and_then(|b| client.get::<Buffer>(b));
|
self.state.lock().pending.buffer = buffer.and_then(|b| {
|
||||||
|
let buffer = client.get::<Buffer>(b)?;
|
||||||
|
Some(BufferState {
|
||||||
|
usage: BufferUsage::new(client, &buffer),
|
||||||
|
buffer,
|
||||||
|
})
|
||||||
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,8 +250,6 @@ impl WlSurface for Surface {
|
|||||||
_width: i32,
|
_width: i32,
|
||||||
_height: i32,
|
_height: i32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// should be more intelligent about this but for now just make it copy everything to gpu next frame again
|
|
||||||
self.mark_dirty();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,32 +293,7 @@ impl WlSurface for Surface {
|
|||||||
/// https://wayland.app/protocols/wayland#wl_surface:request:commit
|
/// https://wayland.app/protocols/wayland#wl_surface:request:commit
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
#[tracing::instrument(level = "debug", skip_all)]
|
||||||
async fn commit(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> {
|
async fn commit(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> {
|
||||||
{
|
self.state.lock().apply();
|
||||||
let mut lock = self.state.lock();
|
|
||||||
|
|
||||||
// If we're getting a new buffer and the current one is DMA-BUF, release it
|
|
||||||
if let Some(new_buffer) = &lock.pending.buffer {
|
|
||||||
if let Some(current_buffer) = &lock.current().buffer {
|
|
||||||
// Don't release if it's the same buffer being reused
|
|
||||||
if !Arc::ptr_eq(new_buffer, current_buffer)
|
|
||||||
&& !current_buffer.can_release_after_update()
|
|
||||||
{
|
|
||||||
let _ = self
|
|
||||||
.message_sink
|
|
||||||
.send(Message::ReleaseBuffer(current_buffer.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let dirty = lock.current().clean_lock.get().is_none()
|
|
||||||
|| lock.pending.clean_lock.take().is_none();
|
|
||||||
lock.apply();
|
|
||||||
|
|
||||||
if !dirty {
|
|
||||||
let _ = lock.current().clean_lock.set(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let current_state = self.current_state();
|
let current_state = self.current_state();
|
||||||
let mut handlers = self.on_commit_handlers.lock();
|
let mut handlers = self.on_commit_handlers.lock();
|
||||||
handlers.retain(|f| (f)(self, ¤t_state));
|
handlers.retain(|f| (f)(self, ¤t_state));
|
||||||
@@ -358,8 +335,6 @@ impl WlSurface for Surface {
|
|||||||
_width: i32,
|
_width: i32,
|
||||||
_height: i32,
|
_height: i32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// we should upload only chunks to the gpu and do subimage copy but that's a lot rn so we won't
|
|
||||||
self.mark_dirty();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
use super::buffer_params::BufferParams;
|
use super::buffer_params::BufferParams;
|
||||||
use crate::wayland::{MessageSink, RENDER_DEVICE};
|
use crate::{
|
||||||
|
core::registry::Registry,
|
||||||
|
wayland::{MessageSink, RENDER_DEVICE, core::buffer::BufferUsage},
|
||||||
|
};
|
||||||
use bevy::{
|
use bevy::{
|
||||||
asset::{Assets, Handle},
|
asset::{Assets, Handle},
|
||||||
image::Image,
|
image::Image,
|
||||||
@@ -12,8 +15,12 @@ use drm_fourcc::DrmFourcc;
|
|||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::sync::{Arc, OnceLock};
|
use std::sync::{Arc, OnceLock};
|
||||||
|
use tracing::info;
|
||||||
use waynest::server::protocol::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::Flags;
|
use waynest::server::protocol::stable::linux_dmabuf_v1::zwp_linux_buffer_params_v1::Flags;
|
||||||
|
|
||||||
|
// clear this out on end frame, add to it whenever a commit with the surface with the buffer is present
|
||||||
|
const IN_USE_DMABUFS: Registry<BufferUsage> = Registry::new();
|
||||||
|
|
||||||
/// Parameters for a shared memory buffer
|
/// Parameters for a shared memory buffer
|
||||||
pub struct DmabufBacking {
|
pub struct DmabufBacking {
|
||||||
message_sink: Option<MessageSink>,
|
message_sink: Option<MessageSink>,
|
||||||
@@ -81,7 +88,10 @@ impl DmabufBacking {
|
|||||||
&self,
|
&self,
|
||||||
dmatexes: &ImportedDmatexs,
|
dmatexes: &ImportedDmatexs,
|
||||||
images: &mut Assets<Image>,
|
images: &mut Assets<Image>,
|
||||||
|
usage: Arc<BufferUsage>,
|
||||||
) -> Option<Handle<Image>> {
|
) -> Option<Handle<Image>> {
|
||||||
|
IN_USE_DMABUFS.add_raw(usage);
|
||||||
|
info!("updating dmabuf tex");
|
||||||
self.pending_imported_dmatex
|
self.pending_imported_dmatex
|
||||||
.lock()
|
.lock()
|
||||||
.take()
|
.take()
|
||||||
|
|||||||
@@ -21,15 +21,9 @@ use bevy::render::{Render, RenderApp};
|
|||||||
use bevy::{asset::Assets, ecs::resource::Resource, image::Image};
|
use bevy::{asset::Assets, ecs::resource::Resource, image::Image};
|
||||||
use bevy_dmabuf::import::ImportedDmatexs;
|
use bevy_dmabuf::import::ImportedDmatexs;
|
||||||
use cluFlock::{FlockLock, ToFlock};
|
use cluFlock::{FlockLock, ToFlock};
|
||||||
use core::{
|
use core::{buffer::Buffer, callback::Callback, display::Display, surface::WL_SURFACE_REGISTRY};
|
||||||
buffer::{Buffer, WL_BUFFER_REGISTRY},
|
|
||||||
callback::Callback,
|
|
||||||
display::Display,
|
|
||||||
surface::WL_SURFACE_REGISTRY,
|
|
||||||
};
|
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::sync::atomic::Ordering;
|
|
||||||
use std::{
|
use std::{
|
||||||
fs::{self, OpenOptions},
|
fs::{self, OpenOptions},
|
||||||
io::{self, ErrorKind},
|
io::{self, ErrorKind},
|
||||||
@@ -307,14 +301,6 @@ fn init_render_device(dev: Res<RenderDevice>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn early_frame() {
|
fn early_frame() {
|
||||||
for buffer in WL_BUFFER_REGISTRY.get_valid_contents() {
|
|
||||||
if buffer.rendered.load(Ordering::Relaxed) {
|
|
||||||
let _ = buffer
|
|
||||||
.message_sink
|
|
||||||
.send(Message::ReleaseBuffer(buffer.clone()));
|
|
||||||
}
|
|
||||||
buffer.rendered.store(false, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
for surface in WL_SURFACE_REGISTRY.get_valid_contents() {
|
for surface in WL_SURFACE_REGISTRY.get_valid_contents() {
|
||||||
surface.frame_event();
|
surface.frame_event();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ impl Backend for XdgBackend {
|
|||||||
|
|
||||||
let size = surface_state
|
let size = surface_state
|
||||||
.buffer
|
.buffer
|
||||||
.map(|b| [b.size().x as u32, b.size().y as u32].into())
|
.map(|b| [b.buffer.size().x as u32, b.buffer.size().y as u32].into())
|
||||||
.unwrap_or([0; 2].into());
|
.unwrap_or([0; 2].into());
|
||||||
let toplevel = ToplevelInfo {
|
let toplevel = ToplevelInfo {
|
||||||
parent: self.toplevel().parent(),
|
parent: self.toplevel().parent(),
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ impl XdgSurface for Surface {
|
|||||||
let has_valid_buffer = state
|
let has_valid_buffer = state
|
||||||
.buffer
|
.buffer
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.is_some_and(|b| b.size().x > 0 && b.size().y > 0);
|
.is_some_and(|b| b.buffer.size().x > 0 && b.buffer.size().y > 0);
|
||||||
|
|
||||||
let mut mapped_lock = toplevel.mapped.lock();
|
let mut mapped_lock = toplevel.mapped.lock();
|
||||||
if mapped_lock.is_none()
|
if mapped_lock.is_none()
|
||||||
@@ -161,7 +161,7 @@ impl XdgSurface for Surface {
|
|||||||
// let has_valid_buffer = state
|
// let has_valid_buffer = state
|
||||||
// .buffer
|
// .buffer
|
||||||
// .as_ref()
|
// .as_ref()
|
||||||
// .is_some_and(|b| b.size().x > 0 && b.size().y > 0);
|
// .is_some_and(|b| b.buffer.size().x > 0 && b.buffer.size().y > 0);
|
||||||
|
|
||||||
// let mut mapped_lock = popup.mapped.lock();
|
// let mut mapped_lock = popup.mapped.lock();
|
||||||
// if mapped_lock.is_none()
|
// if mapped_lock.is_none()
|
||||||
|
|||||||
Reference in New Issue
Block a user