@@ -7,73 +7,65 @@ use ndk::{
77 hardware_buffer_format:: HardwareBufferFormat ,
88 native_window:: { NativeWindow , NativeWindowBufferLockGuard } ,
99} ;
10+ #[ cfg( doc) ]
11+ use raw_window_handle:: AndroidNdkWindowHandle ;
1012use raw_window_handle:: { HasDisplayHandle , HasWindowHandle , RawWindowHandle } ;
1113
1214use crate :: error:: InitError ;
13- use crate :: { Rect , SoftBufferError } ;
15+ use crate :: { BufferInterface , Rect , SoftBufferError , SurfaceInterface } ;
1416
1517/// The handle to a window for software buffering.
16- pub struct AndroidImpl < D : ? Sized , W : ? Sized > {
18+ pub struct AndroidImpl < D , W > {
1719 native_window : NativeWindow ,
18-
19- _display : PhantomData < D > ,
20-
21- /// The pointer to the window object.
22- ///
23- /// This is pretty useless because it gives us a pointer to [`NativeWindow`] that we have to increase the refcount on.
24- /// Alternatively we can use [`NativeWindow::from_ptr()`] wrapped in [`std::mem::ManuallyDrop`]
2520 window : W ,
21+ _display : PhantomData < D > ,
2622}
2723
28- // TODO: Current system doesn't require a trait to be implemented here, even though it exists.
29- impl < D : HasDisplayHandle , W : HasWindowHandle > AndroidImpl < D , W > {
24+ impl < D : HasDisplayHandle , W : HasWindowHandle > SurfaceInterface < D , W > for AndroidImpl < D , W > {
25+ type Context = D ;
26+ type Buffer < ' a >
27+ = BufferImpl < ' a , D , W >
28+ where
29+ Self : ' a ;
30+
3031 /// Create a new [`AndroidImpl`] from an [`AndroidNdkWindowHandle`].
31- ///
32- /// # Safety
33- ///
34- /// The [`AndroidNdkWindowHandle`] must be a valid window handle.
35- // TODO: That's lame, why can't we get an AndroidNdkWindowHandle directly here
36- pub ( crate ) fn new ( window : W , _display : & D ) -> Result < Self , InitError < W > > {
37- // Get the raw Android window (surface).
32+ fn new ( window : W , _display : & Self :: Context ) -> Result < Self , InitError < W > > {
3833 let raw = window. window_handle ( ) ?. as_raw ( ) ;
3934 let RawWindowHandle :: AndroidNdk ( a) = raw else {
4035 return Err ( InitError :: Unsupported ( window) ) ;
4136 } ;
4237
4338 // Acquire a new owned reference to the window, that will be freed on drop.
39+ // SAFETY: We have confirmed that the window handle is valid.
4440 let native_window = unsafe { NativeWindow :: clone_from_ptr ( a. a_native_window . cast ( ) ) } ;
4541
4642 Ok ( Self {
4743 native_window,
48- // _display: DisplayHandle::borrow_raw(raw_window_handle::RawDisplayHandle::Android(
49- // AndroidDisplayHandle,
50- // )),
5144 _display : PhantomData ,
5245 window,
5346 } )
5447 }
5548
5649 #[ inline]
57- pub fn window ( & self ) -> & W {
50+ fn window ( & self ) -> & W {
5851 & self . window
5952 }
6053
6154 /// Also changes the pixel format to [`HardwareBufferFormat::R8G8B8A8_UNORM`].
62- pub fn resize ( & mut self , width : NonZeroU32 , height : NonZeroU32 ) -> Result < ( ) , SoftBufferError > {
55+ fn resize ( & mut self , width : NonZeroU32 , height : NonZeroU32 ) -> Result < ( ) , SoftBufferError > {
6356 let ( width, height) = ( || {
6457 let width = NonZeroI32 :: try_from ( width) . ok ( ) ?;
6558 let height = NonZeroI32 :: try_from ( height) . ok ( ) ?;
6659 Some ( ( width, height) )
6760 } ) ( )
6861 . ok_or ( SoftBufferError :: SizeOutOfRange { width, height } ) ?;
6962
70- // Do not change the format.
7163 self . native_window
7264 . set_buffers_geometry (
7365 width. into ( ) ,
7466 height. into ( ) ,
7567 // Default is typically R5G6B5 16bpp, switch to 32bpp
76- Some ( HardwareBufferFormat :: R8G8B8A8_UNORM ) ,
68+ Some ( HardwareBufferFormat :: R8G8B8X8_UNORM ) ,
7769 )
7870 . map_err ( |err| {
7971 SoftBufferError :: PlatformError (
@@ -83,72 +75,98 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> AndroidImpl<D, W> {
8375 } )
8476 }
8577
86- pub fn buffer_mut ( & mut self ) -> Result < BufferImpl < ' _ , D , W > , SoftBufferError > {
87- let lock_guard = self . native_window . lock ( None ) . map_err ( |err| {
78+ fn buffer_mut ( & mut self ) -> Result < BufferImpl < ' _ , D , W > , SoftBufferError > {
79+ let native_window_buffer = self . native_window . lock ( None ) . map_err ( |err| {
8880 SoftBufferError :: PlatformError (
8981 Some ( "Failed to lock ANativeWindow" . to_owned ( ) ) ,
9082 Some ( Box :: new ( err) ) ,
9183 )
9284 } ) ?;
9385
94- assert_eq ! (
95- lock_guard. format( ) . bytes_per_pixel( ) ,
96- Some ( 4 ) ,
97- "Unexpected buffer format {:?}, please call .resize() first to change it to RGBA8888" ,
98- lock_guard. format( )
99- ) ;
86+ if !matches ! (
87+ native_window_buffer. format( ) ,
88+ // These are the only formats we support
89+ HardwareBufferFormat :: R8G8B8A8_UNORM | HardwareBufferFormat :: R8G8B8X8_UNORM
90+ ) {
91+ return Err ( SoftBufferError :: PlatformError (
92+ Some ( format ! (
93+ "Unexpected buffer format {:?}, please call \
94+ .resize() first to change it to RGBx8888",
95+ native_window_buffer. format( )
96+ ) ) ,
97+ None ,
98+ ) ) ;
99+ }
100+
101+ let buffer = vec ! [ 0 ; native_window_buffer. width( ) * native_window_buffer. height( ) ] ;
100102
101- Ok ( BufferImpl ( lock_guard, PhantomData , PhantomData ) )
103+ Ok ( BufferImpl {
104+ native_window_buffer,
105+ buffer,
106+ marker : PhantomData ,
107+ } )
102108 }
103109
104110 /// Fetch the buffer from the window.
105- pub fn fetch ( & mut self ) -> Result < Vec < u32 > , SoftBufferError > {
111+ fn fetch ( & mut self ) -> Result < Vec < u32 > , SoftBufferError > {
106112 Err ( SoftBufferError :: Unimplemented )
107113 }
108114}
109115
110- pub struct BufferImpl < ' a , D : ?Sized , W > (
111- NativeWindowBufferLockGuard < ' a > ,
112- PhantomData < & ' a D > ,
113- PhantomData < & ' a W > ,
114- ) ;
116+ pub struct BufferImpl < ' a , D : ?Sized , W > {
117+ native_window_buffer : NativeWindowBufferLockGuard < ' a > ,
118+ buffer : Vec < u32 > ,
119+ marker : PhantomData < ( & ' a D , & ' a W ) > ,
120+ }
115121
116122// TODO: Move to NativeWindowBufferLockGuard?
117123unsafe impl < ' a , D , W > Send for BufferImpl < ' a , D , W > { }
118124
119- impl < ' a , D : HasDisplayHandle + ? Sized , W : HasWindowHandle > BufferImpl < ' a , D , W > {
125+ impl < ' a , D : HasDisplayHandle , W : HasWindowHandle > BufferInterface for BufferImpl < ' a , D , W > {
120126 #[ inline]
121- pub fn pixels ( & self ) -> & [ u32 ] {
122- todo ! ( )
123- // unsafe {
124- // std::slice::from_raw_parts(
125- // self.0.bits().cast_const().cast(),
126- // (self.0.stride() * self.0.height()) as usize,
127- // )
128- // }
127+ fn pixels ( & self ) -> & [ u32 ] {
128+ & self . buffer
129129 }
130130
131131 #[ inline]
132- pub fn pixels_mut ( & mut self ) -> & mut [ u32 ] {
133- let bytes = self . 0 . bytes ( ) . expect ( "Nonplanar format" ) ;
134- unsafe {
135- std:: slice:: from_raw_parts_mut (
136- bytes. as_mut_ptr ( ) . cast ( ) ,
137- bytes. len ( ) / std:: mem:: size_of :: < u32 > ( ) ,
138- )
139- }
132+ fn pixels_mut ( & mut self ) -> & mut [ u32 ] {
133+ & mut self . buffer
140134 }
141135
142- pub fn age ( & self ) -> u8 {
136+ #[ inline]
137+ fn age ( & self ) -> u8 {
143138 0
144139 }
145140
146- pub fn present ( self ) -> Result < ( ) , SoftBufferError > {
147- // Dropping the guard automatically unlocks and posts it
141+ // TODO: This function is pretty slow this way
142+ fn present ( mut self ) -> Result < ( ) , SoftBufferError > {
143+ let input_lines = self . buffer . chunks ( self . native_window_buffer . width ( ) ) ;
144+ for ( output, input) in self
145+ . native_window_buffer
146+ . lines ( )
147+ // Unreachable as we checked before that this is a valid, mappable format
148+ . unwrap ( )
149+ . zip ( input_lines)
150+ {
151+ // .lines() removed the stride
152+ assert_eq ! ( output. len( ) , input. len( ) * 4 ) ;
153+
154+ for ( i, pixel) in input. iter ( ) . enumerate ( ) {
155+ // Swizzle colors from RGBX to BGR
156+ let [ b, g, r, _] = pixel. to_le_bytes ( ) ;
157+ output[ i * 4 ] . write ( b) ;
158+ output[ i * 4 + 1 ] . write ( g) ;
159+ output[ i * 4 + 2 ] . write ( r) ;
160+ // TODO alpha?
161+ }
162+ }
148163 Ok ( ( ) )
149164 }
150165
151- pub fn present_with_damage ( self , _damage : & [ Rect ] ) -> Result < ( ) , SoftBufferError > {
152- Err ( SoftBufferError :: Unimplemented )
166+ fn present_with_damage ( self , _damage : & [ Rect ] ) -> Result < ( ) , SoftBufferError > {
167+ // TODO: Android requires the damage rect _at lock time_
168+ // Since we're faking the backing buffer _anyway_, we could even fake the surface lock
169+ // and lock it here (if it doesn't influence timings).
170+ self . present ( )
153171 }
154172}
0 commit comments