diff --git a/src/backends/metal/transaction.rs b/src/backends/metal/transaction.rs index 52882917..417fdd24 100644 --- a/src/backends/metal/transaction.rs +++ b/src/backends/metal/transaction.rs @@ -13,7 +13,7 @@ use { RenderBuffer, }, format::{ARGB8888, Format}, - gfx_api::{AcquireSync, ReleaseSync, SyncFile}, + gfx_api::SyncFile, utils::{ binary_search_map::BinarySearchMap, cell_ext::CellExt, errorfmt::ErrorFmt, rc_eq::rc_eq, }, @@ -567,34 +567,22 @@ impl MetalDeviceTransaction { let cd = connector.obj.color_description.get(); let res = if let Some(prev) = &old_buffers && let Some(prev) = prev.iter().find(|b| b.drm.id() == fb_id) - && rc_eq(&new_buffer.dev_ctx, &prev.dev_ctx) && may_show_current_fb { - let src = prev.dev_tex.as_ref().unwrap_or(&prev.render_tex); - let dst = &new_buffer.dev_fb; - dst.copy_texture( - AcquireSync::Unnecessary, - ReleaseSync::Explicit, - &cd, - src, - &cd, - None, - AcquireSync::Unnecessary, - ReleaseSync::Explicit, - 0, - 0, - ) + match prev.copy_to_new(new_buffer, &cd) { + Ok(sf) => Ok(sf), + Err(e) => { + log::warn!("Could not copy from old buffer: {}", ErrorFmt(&*e)); + new_buffer.clear(&cd) + } + } } else { - new_buffer.dev_fb.clear( - AcquireSync::Unnecessary, - ReleaseSync::Explicit, - &cd, - ) + new_buffer.clear(&cd) }; match res { Ok(sf) => sync_files.extend(sf), Err(e) => { - log::warn!("Could not copy from old buffer: {}", ErrorFmt(e)); + log::warn!("Could not clear new buffer: {}", ErrorFmt(&*e)); } } } else { @@ -626,11 +614,7 @@ impl MetalDeviceTransaction { } buffer.damage_full(); let cd = connector.obj.color_description.get(); - let res = buffer.dev_fb.clear( - AcquireSync::Unnecessary, - ReleaseSync::Explicit, - &cd, - ); + let res = buffer.clear(&cd); match res { Ok(sf) => { buffer.locked.set(true); @@ -639,7 +623,7 @@ impl MetalDeviceTransaction { Err(e) => { log::error!( "Could not black out old buffer: {}", - ErrorFmt(e), + ErrorFmt(&*e), ); } } diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index 16e8eb93..0faa76bc 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -41,7 +41,7 @@ use { asyncevent::AsyncEvent, binary_search_map::BinarySearchMap, bitflags::BitflagsExt, cell_ext::CellExt, clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, geometric_decay::GeometricDecay, numcell::NumCell, on_change::OnChange, - opaque_cell::OpaqueCell, ordered_float::F64, oserror::OsError, + opaque_cell::OpaqueCell, ordered_float::F64, oserror::OsError, rc_eq::rc_eq, }, video::{ INVALID_MODIFIER, Modifier, @@ -66,6 +66,7 @@ use { std::{ cell::{Cell, RefCell}, collections::hash_map::Entry, + error::Error, ffi::CString, fmt::{Debug, Formatter}, mem, @@ -3021,4 +3022,43 @@ impl RenderBuffer { self.damage_queue.clear_all(); self.damage_queue.damage(&[rect]); } + + pub fn clear(&self, cd: &Rc) -> Result, Box> { + self.dev_fb + .clear(AcquireSync::Unnecessary, ReleaseSync::Explicit, cd) + .map_err(Into::into) + } + + pub fn copy_to_new( + &self, + new: &Self, + cd: &Rc, + ) -> Result, Box> { + let old = self; + let copy_texture = |new: &Rc, old: &Rc| { + new.copy_texture( + AcquireSync::Unnecessary, + ReleaseSync::Explicit, + cd, + old, + cd, + None, + AcquireSync::Unnecessary, + ReleaseSync::Explicit, + 0, + 0, + ) + .map_err(Into::into) + }; + if rc_eq(&old.dev_ctx, &new.dev_ctx) { + return copy_texture(&new.dev_fb, old.dev_tex.as_ref().unwrap_or(&old.render_tex)); + } + let tex = new + .dev_ctx + .gfx + .clone() + .dmabuf_img(old.dev_bo.dmabuf())? + .to_texture()?; + copy_texture(&new.dev_fb, &tex) + } }