wl_surface: handle buffer release automatically
This commit is contained in:
parent
6bdd1ff6e7
commit
8f576f498e
5 changed files with 51 additions and 34 deletions
|
|
@ -48,6 +48,19 @@ pub struct DmabufBufferParams {
|
||||||
tex_impossible: bool,
|
tex_impossible: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AttachedBuffer {
|
||||||
|
pub send_release: bool,
|
||||||
|
pub buf: Rc<WlBuffer>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for AttachedBuffer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if self.send_release && !self.buf.destroyed() {
|
||||||
|
self.buf.send_release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct WlBuffer {
|
pub struct WlBuffer {
|
||||||
pub id: WlBufferId,
|
pub id: WlBufferId,
|
||||||
destroyed: Cell<bool>,
|
destroyed: Cell<bool>,
|
||||||
|
|
@ -507,7 +520,7 @@ impl WlBuffer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_release(&self) {
|
fn send_release(&self) {
|
||||||
self.client.event(Release { self_id: self.id })
|
self.client.event(Release { self_id: self.id })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ use {
|
||||||
},
|
},
|
||||||
ifs::{
|
ifs::{
|
||||||
color_management::wp_color_management_surface_feedback_v1::WpColorManagementSurfaceFeedbackV1,
|
color_management::wp_color_management_surface_feedback_v1::WpColorManagementSurfaceFeedbackV1,
|
||||||
wl_buffer::WlBuffer,
|
wl_buffer::AttachedBuffer,
|
||||||
wl_callback::WlCallback,
|
wl_callback::WlCallback,
|
||||||
wl_seat::{
|
wl_seat::{
|
||||||
Dnd, NodeSeatState, SeatId, WlSeatGlobal,
|
Dnd, NodeSeatState, SeatId, WlSeatGlobal,
|
||||||
|
|
@ -217,7 +217,7 @@ struct SurfaceBufferExplicitRelease {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SurfaceBuffer {
|
pub struct SurfaceBuffer {
|
||||||
pub buffer: Rc<WlBuffer>,
|
pub buffer: AttachedBuffer,
|
||||||
sync_files: SmallMap<BufferResvUser, SyncFile, 1>,
|
sync_files: SmallMap<BufferResvUser, SyncFile, 1>,
|
||||||
pub release_sync: ReleaseSync,
|
pub release_sync: ReleaseSync,
|
||||||
release: Option<SurfaceBufferExplicitRelease>,
|
release: Option<SurfaceBufferExplicitRelease>,
|
||||||
|
|
@ -227,7 +227,7 @@ impl Drop for SurfaceBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let sync_files = self.sync_files.take();
|
let sync_files = self.sync_files.take();
|
||||||
if let Some(release) = &self.release {
|
if let Some(release) = &self.release {
|
||||||
let Some(ctx) = self.buffer.client.state.render_ctx.get() else {
|
let Some(ctx) = self.buffer.buf.client.state.render_ctx.get() else {
|
||||||
log::error!("Cannot signal release point because there is no render context");
|
log::error!("Cannot signal release point because there is no render context");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
@ -253,16 +253,13 @@ impl Drop for SurfaceBuffer {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(dmabuf) = &self.buffer.client_dmabuf {
|
if let Some(dmabuf) = &self.buffer.buf.client_dmabuf {
|
||||||
for (_, sync_file) in &sync_files {
|
for (_, sync_file) in &sync_files {
|
||||||
if let Err(e) = dmabuf.import_sync_file(DMA_BUF_SYNC_READ, sync_file) {
|
if let Err(e) = dmabuf.import_sync_file(DMA_BUF_SYNC_READ, sync_file) {
|
||||||
log::error!("Could not import sync file: {}", ErrorFmt(e));
|
log::error!("Could not import sync file: {}", ErrorFmt(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !self.buffer.destroyed() {
|
|
||||||
self.buffer.send_release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -461,7 +458,7 @@ impl SurfaceExt for NoneSurfaceExt {
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct PendingState {
|
struct PendingState {
|
||||||
buffer: Option<Option<Rc<WlBuffer>>>,
|
buffer: Option<Option<AttachedBuffer>>,
|
||||||
offset: (i32, i32),
|
offset: (i32, i32),
|
||||||
opaque_region: Option<Option<Rc<Region>>>,
|
opaque_region: Option<Option<Rc<Region>>>,
|
||||||
input_region: Option<Option<Rc<Region>>>,
|
input_region: Option<Option<Rc<Region>>>,
|
||||||
|
|
@ -505,10 +502,6 @@ impl PendingState {
|
||||||
if next.buffer.is_some() {
|
if next.buffer.is_some() {
|
||||||
if let Some((sync_obj, point)) = self.release_point.take() {
|
if let Some((sync_obj, point)) = self.release_point.take() {
|
||||||
client.state.signal_point(&sync_obj, point);
|
client.state.signal_point(&sync_obj, point);
|
||||||
} else if let Some(Some(prev)) = self.buffer.take() {
|
|
||||||
if !prev.destroyed() {
|
|
||||||
prev.send_release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.presentation_feedback.clear();
|
self.presentation_feedback.clear();
|
||||||
|
|
@ -1074,7 +1067,10 @@ impl WlSurfaceRequestHandler for WlSurface {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
pending.buffer = Some(buf);
|
pending.buffer = Some(buf.map(|buf| AttachedBuffer {
|
||||||
|
send_release: false,
|
||||||
|
buf,
|
||||||
|
}));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1122,6 +1118,11 @@ impl WlSurfaceRequestHandler for WlSurface {
|
||||||
fn commit(&self, _req: Commit, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
fn commit(&self, _req: Commit, slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
let ext = self.ext.get();
|
let ext = self.ext.get();
|
||||||
let pending = &mut *self.pending.borrow_mut();
|
let pending = &mut *self.pending.borrow_mut();
|
||||||
|
if let Some(Some(buffer)) = &mut pending.buffer
|
||||||
|
&& pending.release_point.is_none()
|
||||||
|
{
|
||||||
|
buffer.send_release = true;
|
||||||
|
}
|
||||||
self.verify_explicit_sync(pending)?;
|
self.verify_explicit_sync(pending)?;
|
||||||
if ext.commit_requested(pending) == CommitAction::ContinueCommit {
|
if ext.commit_requested(pending) == CommitAction::ContinueCommit {
|
||||||
self.commit_timeline.commit(slf, pending)?;
|
self.commit_timeline.commit(slf, pending)?;
|
||||||
|
|
@ -1227,16 +1228,16 @@ 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.buffer.rect);
|
old_raw_size = Some(buffer.buffer.buf.rect);
|
||||||
}
|
}
|
||||||
if let Some(buffer) = buffer_change {
|
if let Some(buffer) = buffer_change {
|
||||||
if buffer.is_shm() {
|
if buffer.buf.is_shm() {
|
||||||
self.shm_textures.flip();
|
self.shm_textures.flip();
|
||||||
self.shm_textures.front().damage.clear();
|
self.shm_textures.front().damage.clear();
|
||||||
} else {
|
} else {
|
||||||
self.reset_shm_textures();
|
self.reset_shm_textures();
|
||||||
}
|
}
|
||||||
buffer.update_texture_or_log(self, false);
|
buffer.buf.update_texture_or_log(self, false);
|
||||||
let release_sync = match pending.explicit_sync {
|
let release_sync = match pending.explicit_sync {
|
||||||
false => ReleaseSync::Implicit,
|
false => ReleaseSync::Implicit,
|
||||||
true => ReleaseSync::Explicit,
|
true => ReleaseSync::Explicit,
|
||||||
|
|
@ -1304,11 +1305,10 @@ impl WlSurface {
|
||||||
new_size = Some(size);
|
new_size = Some(size);
|
||||||
}
|
}
|
||||||
if let Some(buffer) = self.buffer.get() {
|
if let Some(buffer) = self.buffer.get() {
|
||||||
|
let buf = &buffer.buffer.buf;
|
||||||
if new_size.is_none() {
|
if new_size.is_none() {
|
||||||
let (mut width, mut height) = self
|
let (mut width, mut height) =
|
||||||
.buffer_transform
|
self.buffer_transform.get().maybe_swap(buf.rect.size());
|
||||||
.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;
|
||||||
|
|
@ -1316,14 +1316,12 @@ impl WlSurface {
|
||||||
}
|
}
|
||||||
new_size = Some((width, height));
|
new_size = Some((width, height));
|
||||||
}
|
}
|
||||||
if transform_changed || Some(buffer.buffer.rect) != old_raw_size {
|
if transform_changed || Some(buf.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) = self
|
let (width, height) =
|
||||||
.buffer_transform
|
self.buffer_transform.get().maybe_swap(buf.rect.size());
|
||||||
.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;
|
||||||
|
|
@ -1342,7 +1340,7 @@ impl WlSurface {
|
||||||
y2,
|
y2,
|
||||||
buffer_transform: self.buffer_transform.get(),
|
buffer_transform: self.buffer_transform.get(),
|
||||||
};
|
};
|
||||||
let (buffer_width, buffer_height) = buffer.buffer.rect.size();
|
let (buffer_width, buffer_height) = buf.rect.size();
|
||||||
let (mut dst_width, mut dst_height) = new_size.unwrap_or_default();
|
let (mut dst_width, mut dst_height) = new_size.unwrap_or_default();
|
||||||
client_wire_scale_to_logical!(self.client, dst_width, dst_height);
|
client_wire_scale_to_logical!(self.client, dst_width, dst_height);
|
||||||
let damage_matrix = DamageMatrix::new(
|
let damage_matrix = DamageMatrix::new(
|
||||||
|
|
@ -1513,8 +1511,11 @@ impl WlSurface {
|
||||||
let matrix = self.damage_matrix.get();
|
let matrix = self.damage_matrix.get();
|
||||||
if let Some(buffer) = self.buffer.get() {
|
if let Some(buffer) = self.buffer.get() {
|
||||||
for damage in &pending.buffer_damage {
|
for damage in &pending.buffer_damage {
|
||||||
let mut damage =
|
let mut damage = matrix.apply(
|
||||||
matrix.apply(pos.x1(), pos.y1(), damage.intersect(buffer.buffer.rect));
|
pos.x1(),
|
||||||
|
pos.y1(),
|
||||||
|
damage.intersect(buffer.buffer.buf.rect),
|
||||||
|
);
|
||||||
if let Some(bounds) = bounds {
|
if let Some(bounds) = bounds {
|
||||||
damage = damage.intersect(bounds);
|
damage = damage.intersect(bounds);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -598,6 +598,7 @@ fn schedule_async_upload(
|
||||||
let Some(Some(buf)) = &pending.buffer else {
|
let Some(Some(buf)) = &pending.buffer else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
let buf = &buf.buf;
|
||||||
let Some(WlBufferStorage::Shm {
|
let Some(WlBufferStorage::Shm {
|
||||||
mem,
|
mem,
|
||||||
stride,
|
stride,
|
||||||
|
|
@ -698,6 +699,7 @@ struct CommitDataCollector {
|
||||||
impl CommitDataCollector {
|
impl CommitDataCollector {
|
||||||
fn collect(&mut self, pending: &mut PendingState) {
|
fn collect(&mut self, pending: &mut PendingState) {
|
||||||
if let Some(Some(buffer)) = &pending.buffer {
|
if let Some(Some(buffer)) = &pending.buffer {
|
||||||
|
let buffer = &buffer.buf;
|
||||||
if buffer.is_shm() {
|
if buffer.is_shm() {
|
||||||
self.shm_uploads += 1;
|
self.shm_uploads += 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -468,10 +468,11 @@ impl Renderer<'_> {
|
||||||
tsize: (i32, i32),
|
tsize: (i32, i32),
|
||||||
bounds: Option<&Rect>,
|
bounds: Option<&Rect>,
|
||||||
) {
|
) {
|
||||||
|
let buf = &buffer.buffer.buf;
|
||||||
let alpha = surface.alpha();
|
let alpha = surface.alpha();
|
||||||
let cd = surface.color_description();
|
let cd = surface.color_description();
|
||||||
let alpha_mode = surface.alpha_mode();
|
let alpha_mode = surface.alpha_mode();
|
||||||
if let Some(tex) = buffer.buffer.get_texture(surface) {
|
if let Some(tex) = buf.get_texture(surface) {
|
||||||
let mut opaque = surface.opaque();
|
let mut opaque = surface.opaque();
|
||||||
if !opaque && tex.format().has_alpha {
|
if !opaque && tex.format().has_alpha {
|
||||||
opaque = self.bounds_are_opaque(x, y, bounds, surface);
|
opaque = self.bounds_are_opaque(x, y, bounds, surface);
|
||||||
|
|
@ -492,7 +493,7 @@ impl Renderer<'_> {
|
||||||
&cd,
|
&cd,
|
||||||
alpha_mode,
|
alpha_mode,
|
||||||
);
|
);
|
||||||
} else if let Some(color) = &buffer.buffer.color {
|
} else if let Some(color) = &buf.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,
|
||||||
|
|
|
||||||
|
|
@ -689,10 +689,10 @@ impl State {
|
||||||
for surface in client.data.objects.surfaces.lock().values() {
|
for surface in client.data.objects.surfaces.lock().values() {
|
||||||
let had_shm_texture = surface.reset_shm_textures();
|
let had_shm_texture = surface.reset_shm_textures();
|
||||||
if let Some(buffer) = surface.buffer.get() {
|
if let Some(buffer) = surface.buffer.get() {
|
||||||
let had_buffer_texture =
|
let buf = &buffer.buffer.buf;
|
||||||
*updated_buffers.get(&Rc::as_ptr(&buffer.buffer)).unwrap();
|
let had_buffer_texture = *updated_buffers.get(&Rc::as_ptr(buf)).unwrap();
|
||||||
if had_shm_texture || had_buffer_texture {
|
if had_shm_texture || had_buffer_texture {
|
||||||
buffer.buffer.update_texture_or_log(surface, true);
|
buf.update_texture_or_log(surface, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue