@@ -20,11 +20,16 @@ const PIXEL_SIZE: usize = size_of::<Pixel>();
2020/// The handle to a window for software buffering.
2121#[ derive( Debug ) ]
2222pub struct AndroidImpl < D , W > {
23+ // Must be first in the struct to guarantee being dropped and unlocked before the `NativeWindow` reference
24+ in_progress_buffer : Option < NativeWindowBufferLockGuard < ' static > > ,
2325 native_window : NativeWindow ,
2426 window : W ,
2527 _display : PhantomData < D > ,
2628}
2729
30+ // TODO: Move to NativeWindowBufferLockGuard?
31+ unsafe impl < D , W > Send for AndroidImpl < D , W > { }
32+
2833impl < D : HasDisplayHandle , W : HasWindowHandle > SurfaceInterface < D , W > for AndroidImpl < D , W > {
2934 type Context = D ;
3035 type Buffer < ' surface >
@@ -44,6 +49,7 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Android
4449 let native_window = unsafe { NativeWindow :: clone_from_ptr ( a. a_native_window . cast ( ) ) } ;
4550
4651 Ok ( Self {
52+ in_progress_buffer : None ,
4753 native_window,
4854 _display : PhantomData ,
4955 window,
@@ -80,6 +86,12 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Android
8086 }
8187
8288 fn next_buffer ( & mut self ) -> Result < BufferImpl < ' _ > , SoftBufferError > {
89+ if self . in_progress_buffer . is_some ( ) {
90+ return Ok ( BufferImpl {
91+ native_window_buffer : & mut self . in_progress_buffer ,
92+ } ) ;
93+ }
94+
8395 let mut native_window_buffer = self . native_window . lock ( None ) . map_err ( |err| {
8496 SoftBufferError :: PlatformError (
8597 Some ( "Failed to lock ANativeWindow" . to_owned ( ) ) ,
@@ -116,8 +128,19 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Android
116128 native_window_buffer. stride( ) * native_window_buffer. height( ) * PIXEL_SIZE
117129 ) ;
118130
131+ // SAFETY: We guarantee that the guard isn't actually held longer than this owned handle of
132+ // the `NativeWindow` (which is trivially cloneable), by means of having BufferImpl take a
133+ // mutable borrow on AndroidImpl which owns the NativeWindow and LockGuard.
134+ let native_window_buffer = unsafe {
135+ std:: mem:: transmute :: <
136+ NativeWindowBufferLockGuard < ' _ > ,
137+ NativeWindowBufferLockGuard < ' static > ,
138+ > ( native_window_buffer)
139+ } ;
140+ self . in_progress_buffer = Some ( native_window_buffer) ;
141+
119142 Ok ( BufferImpl {
120- native_window_buffer,
143+ native_window_buffer : & mut self . in_progress_buffer ,
121144 } )
122145 }
123146
@@ -129,28 +152,30 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Android
129152
130153#[ derive( Debug ) ]
131154pub struct BufferImpl < ' surface > {
132- native_window_buffer : NativeWindowBufferLockGuard < ' surface > ,
155+ // This Option will always be Some until present_with_damage() is called
156+ native_window_buffer : & ' surface mut Option < NativeWindowBufferLockGuard < ' static > > ,
133157}
134158
135159// TODO: Move to NativeWindowBufferLockGuard?
136160unsafe impl Send for BufferImpl < ' _ > { }
137161
138162impl BufferInterface for BufferImpl < ' _ > {
139163 fn byte_stride ( & self ) -> NonZeroU32 {
140- NonZeroU32 :: new ( ( self . native_window_buffer . stride ( ) * PIXEL_SIZE ) as u32 ) . unwrap ( )
164+ NonZeroU32 :: new ( ( self . native_window_buffer . as_ref ( ) . unwrap ( ) . stride ( ) * PIXEL_SIZE ) as u32 )
165+ . unwrap ( )
141166 }
142167
143168 fn width ( & self ) -> NonZeroU32 {
144- NonZeroU32 :: new ( self . native_window_buffer . width ( ) as u32 ) . unwrap ( )
169+ NonZeroU32 :: new ( self . native_window_buffer . as_ref ( ) . unwrap ( ) . width ( ) as u32 ) . unwrap ( )
145170 }
146171
147172 fn height ( & self ) -> NonZeroU32 {
148- NonZeroU32 :: new ( self . native_window_buffer . height ( ) as u32 ) . unwrap ( )
173+ NonZeroU32 :: new ( self . native_window_buffer . as_ref ( ) . unwrap ( ) . height ( ) as u32 ) . unwrap ( )
149174 }
150175
151176 #[ inline]
152177 fn pixels_mut ( & mut self ) -> & mut [ Pixel ] {
153- let native_buffer = self . native_window_buffer . bytes ( ) . unwrap ( ) ;
178+ let native_buffer = self . native_window_buffer . as_mut ( ) . unwrap ( ) . bytes ( ) . unwrap ( ) ;
154179 // SAFETY: The buffer was zero-initialized and its length is always a multiple of the pixel
155180 // size (4 bytes), even when stride is applied
156181 unsafe {
@@ -180,6 +205,7 @@ impl BufferInterface for BufferImpl<'_> {
180205
181206 // The surface will be presented when it is unlocked, which happens when the owned guard
182207 // is dropped.
208+ self . native_window_buffer . take ( ) ;
183209
184210 Ok ( ( ) )
185211 }
0 commit comments