Skip to content

Commit 73cc135

Browse files
committed
Android: Hold the locked buffer in AndroidImpl until it is presented via BufferImpl
1 parent 14ca08b commit 73cc135

File tree

1 file changed

+27
-6
lines changed

1 file changed

+27
-6
lines changed

src/backends/android.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@ use crate::{BufferInterface, Pixel, Rect, SoftBufferError, SurfaceInterface};
1717
/// The handle to a window for software buffering.
1818
#[derive(Debug)]
1919
pub struct AndroidImpl<D, W> {
20+
// Must be first in the struct to guarantee being dropped and unlocked before the `NativeWindow` reference
21+
in_progress_buffer: Option<NativeWindowBufferLockGuard<'static>>,
2022
native_window: NativeWindow,
2123
window: W,
2224
_display: PhantomData<D>,
2325
}
2426

27+
// TODO: Move to NativeWindowBufferLockGuard?
28+
unsafe impl<D, W> Send for AndroidImpl<D, W> {}
29+
2530
impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for AndroidImpl<D, W> {
2631
type Context = D;
2732
type Buffer<'surface>
@@ -41,6 +46,7 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Android
4146
let native_window = unsafe { NativeWindow::clone_from_ptr(a.a_native_window.cast()) };
4247

4348
Ok(Self {
49+
in_progress_buffer: None,
4450
native_window,
4551
_display: PhantomData,
4652
window,
@@ -77,6 +83,12 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Android
7783
}
7884

7985
fn buffer_mut(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
86+
if self.in_progress_buffer.is_some() {
87+
return Ok(BufferImpl {
88+
native_window_buffer: &mut self.in_progress_buffer,
89+
});
90+
}
91+
8092
let native_window_buffer = self.native_window.lock(None).map_err(|err| {
8193
SoftBufferError::PlatformError(
8294
Some("Failed to lock ANativeWindow".to_owned()),
@@ -99,8 +111,15 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Android
99111
));
100112
}
101113

114+
// SAFETY: We guarantee that the guard isn't actually held longer than this owned handle of
115+
// the `NativeWindow` (which is trivially clonable), by means of having BufferImpl take a
116+
// mutable borrow on AndroidImpl which owns the NativeWindow and LockGuard.
117+
let native_window_buffer: NativeWindowBufferLockGuard<'static> =
118+
unsafe { std::mem::transmute(native_window_buffer) };
119+
self.in_progress_buffer = Some(native_window_buffer);
120+
102121
Ok(BufferImpl {
103-
native_window_buffer,
122+
native_window_buffer: &mut self.in_progress_buffer,
104123
})
105124
}
106125

@@ -112,28 +131,29 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Android
112131

113132
#[derive(Debug)]
114133
pub struct BufferImpl<'surface> {
115-
native_window_buffer: NativeWindowBufferLockGuard<'surface>,
134+
// This Option will always be Some until present_with_damage() is called
135+
native_window_buffer: &'surface mut Option<NativeWindowBufferLockGuard<'static>>,
116136
}
117137

118138
// TODO: Move to NativeWindowBufferLockGuard?
119139
unsafe impl Send for BufferImpl<'_> {}
120140

121141
impl BufferInterface for BufferImpl<'_> {
122142
fn byte_stride(&self) -> NonZeroU32 {
123-
NonZeroU32::new(self.native_window_buffer.stride() as u32 * 4).unwrap()
143+
NonZeroU32::new(self.native_window_buffer.as_ref().unwrap().stride() as u32 * 4).unwrap()
124144
}
125145

126146
fn width(&self) -> NonZeroU32 {
127-
NonZeroU32::new(self.native_window_buffer.width() as u32).unwrap()
147+
NonZeroU32::new(self.native_window_buffer.as_ref().unwrap().width() as u32).unwrap()
128148
}
129149

130150
fn height(&self) -> NonZeroU32 {
131-
NonZeroU32::new(self.native_window_buffer.height() as u32).unwrap()
151+
NonZeroU32::new(self.native_window_buffer.as_ref().unwrap().height() as u32).unwrap()
132152
}
133153

134154
#[inline]
135155
fn pixels_mut(&mut self) -> &mut [Pixel] {
136-
let native_buffer = self.native_window_buffer.bytes().unwrap();
156+
let native_buffer = self.native_window_buffer.as_mut().unwrap().bytes().unwrap();
137157
// assert_eq!(
138158
// native_buffer.len(),
139159
// self.native_window_buffer.stride() * self.native_window_buffer.height()
@@ -168,6 +188,7 @@ impl BufferInterface for BufferImpl<'_> {
168188

169189
// The surface will be presented when it is unlocked, which happens when the owned guard
170190
// is dropped.
191+
self.native_window_buffer.take();
171192

172193
Ok(())
173194
}

0 commit comments

Comments
 (0)