1
0
Fork 0
forked from wry/wry

Merge pull request #743 from mahkoh/jorth/preserve-more

metal: preserve render buffer contents in more situations
This commit is contained in:
mahkoh 2026-02-16 15:30:10 +01:00 committed by GitHub
commit 069369e7d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 53 additions and 29 deletions

View file

@ -13,7 +13,7 @@ use {
RenderBuffer, RenderBuffer,
}, },
format::{ARGB8888, Format}, format::{ARGB8888, Format},
gfx_api::{AcquireSync, ReleaseSync, SyncFile}, gfx_api::SyncFile,
utils::{ utils::{
binary_search_map::BinarySearchMap, cell_ext::CellExt, errorfmt::ErrorFmt, rc_eq::rc_eq, 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 cd = connector.obj.color_description.get();
let res = if let Some(prev) = &old_buffers let res = if let Some(prev) = &old_buffers
&& let Some(prev) = prev.iter().find(|b| b.drm.id() == fb_id) && 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 && may_show_current_fb
{ {
let src = prev.dev_tex.as_ref().unwrap_or(&prev.render_tex); match prev.copy_to_new(new_buffer, &cd) {
let dst = &new_buffer.dev_fb; Ok(sf) => Ok(sf),
dst.copy_texture( Err(e) => {
AcquireSync::Unnecessary, log::warn!("Could not copy from old buffer: {}", ErrorFmt(&*e));
ReleaseSync::Explicit, new_buffer.clear(&cd)
&cd, }
src, }
&cd,
None,
AcquireSync::Unnecessary,
ReleaseSync::Explicit,
0,
0,
)
} else { } else {
new_buffer.dev_fb.clear( new_buffer.clear(&cd)
AcquireSync::Unnecessary,
ReleaseSync::Explicit,
&cd,
)
}; };
match res { match res {
Ok(sf) => sync_files.extend(sf), Ok(sf) => sync_files.extend(sf),
Err(e) => { Err(e) => {
log::warn!("Could not copy from old buffer: {}", ErrorFmt(e)); log::warn!("Could not clear new buffer: {}", ErrorFmt(&*e));
} }
} }
} else { } else {
@ -626,11 +614,7 @@ impl MetalDeviceTransaction {
} }
buffer.damage_full(); buffer.damage_full();
let cd = connector.obj.color_description.get(); let cd = connector.obj.color_description.get();
let res = buffer.dev_fb.clear( let res = buffer.clear(&cd);
AcquireSync::Unnecessary,
ReleaseSync::Explicit,
&cd,
);
match res { match res {
Ok(sf) => { Ok(sf) => {
buffer.locked.set(true); buffer.locked.set(true);
@ -639,7 +623,7 @@ impl MetalDeviceTransaction {
Err(e) => { Err(e) => {
log::error!( log::error!(
"Could not black out old buffer: {}", "Could not black out old buffer: {}",
ErrorFmt(e), ErrorFmt(&*e),
); );
} }
} }

View file

@ -41,7 +41,7 @@ use {
asyncevent::AsyncEvent, binary_search_map::BinarySearchMap, bitflags::BitflagsExt, asyncevent::AsyncEvent, binary_search_map::BinarySearchMap, bitflags::BitflagsExt,
cell_ext::CellExt, clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt, cell_ext::CellExt, clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
geometric_decay::GeometricDecay, numcell::NumCell, on_change::OnChange, 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::{ video::{
INVALID_MODIFIER, Modifier, INVALID_MODIFIER, Modifier,
@ -66,6 +66,7 @@ use {
std::{ std::{
cell::{Cell, RefCell}, cell::{Cell, RefCell},
collections::hash_map::Entry, collections::hash_map::Entry,
error::Error,
ffi::CString, ffi::CString,
fmt::{Debug, Formatter}, fmt::{Debug, Formatter},
mem, mem,
@ -3021,4 +3022,43 @@ impl RenderBuffer {
self.damage_queue.clear_all(); self.damage_queue.clear_all();
self.damage_queue.damage(&[rect]); self.damage_queue.damage(&[rect]);
} }
pub fn clear(&self, cd: &Rc<ColorDescription>) -> Result<Option<SyncFile>, Box<dyn Error>> {
self.dev_fb
.clear(AcquireSync::Unnecessary, ReleaseSync::Explicit, cd)
.map_err(Into::into)
}
pub fn copy_to_new(
&self,
new: &Self,
cd: &Rc<ColorDescription>,
) -> Result<Option<SyncFile>, Box<dyn Error>> {
let old = self;
let copy_texture = |new: &Rc<dyn GfxFramebuffer>, old: &Rc<dyn GfxTexture>| {
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)
}
} }