@@ -7,73 +7,65 @@ use ndk::{
7
7
hardware_buffer_format:: HardwareBufferFormat ,
8
8
native_window:: { NativeWindow , NativeWindowBufferLockGuard } ,
9
9
} ;
10
+ #[ cfg( doc) ]
11
+ use raw_window_handle:: AndroidNdkWindowHandle ;
10
12
use raw_window_handle:: { HasDisplayHandle , HasWindowHandle , RawWindowHandle } ;
11
13
12
14
use crate :: error:: InitError ;
13
- use crate :: { Rect , SoftBufferError } ;
15
+ use crate :: { BufferInterface , Rect , SoftBufferError , SurfaceInterface } ;
14
16
15
17
/// The handle to a window for software buffering.
16
- pub struct AndroidImpl < D : ? Sized , W : ? Sized > {
18
+ pub struct AndroidImpl < D , W > {
17
19
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`]
25
20
window : W ,
21
+ _display : PhantomData < D > ,
26
22
}
27
23
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
+
30
31
/// 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 > > {
38
33
let raw = window. window_handle ( ) ?. as_raw ( ) ;
39
34
let RawWindowHandle :: AndroidNdk ( a) = raw else {
40
35
return Err ( InitError :: Unsupported ( window) ) ;
41
36
} ;
42
37
43
38
// 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.
44
40
let native_window = unsafe { NativeWindow :: clone_from_ptr ( a. a_native_window . cast ( ) ) } ;
45
41
46
42
Ok ( Self {
47
43
native_window,
48
- // _display: DisplayHandle::borrow_raw(raw_window_handle::RawDisplayHandle::Android(
49
- // AndroidDisplayHandle,
50
- // )),
51
44
_display : PhantomData ,
52
45
window,
53
46
} )
54
47
}
55
48
56
49
#[ inline]
57
- pub fn window ( & self ) -> & W {
50
+ fn window ( & self ) -> & W {
58
51
& self . window
59
52
}
60
53
61
54
/// 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 > {
63
56
let ( width, height) = ( || {
64
57
let width = NonZeroI32 :: try_from ( width) . ok ( ) ?;
65
58
let height = NonZeroI32 :: try_from ( height) . ok ( ) ?;
66
59
Some ( ( width, height) )
67
60
} ) ( )
68
61
. ok_or ( SoftBufferError :: SizeOutOfRange { width, height } ) ?;
69
62
70
- // Do not change the format.
71
63
self . native_window
72
64
. set_buffers_geometry (
73
65
width. into ( ) ,
74
66
height. into ( ) ,
75
67
// Default is typically R5G6B5 16bpp, switch to 32bpp
76
- Some ( HardwareBufferFormat :: R8G8B8A8_UNORM ) ,
68
+ Some ( HardwareBufferFormat :: R8G8B8X8_UNORM ) ,
77
69
)
78
70
. map_err ( |err| {
79
71
SoftBufferError :: PlatformError (
@@ -83,72 +75,98 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> AndroidImpl<D, W> {
83
75
} )
84
76
}
85
77
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| {
88
80
SoftBufferError :: PlatformError (
89
81
Some ( "Failed to lock ANativeWindow" . to_owned ( ) ) ,
90
82
Some ( Box :: new ( err) ) ,
91
83
)
92
84
} ) ?;
93
85
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( ) ] ;
100
102
101
- Ok ( BufferImpl ( lock_guard, PhantomData , PhantomData ) )
103
+ Ok ( BufferImpl {
104
+ native_window_buffer,
105
+ buffer,
106
+ marker : PhantomData ,
107
+ } )
102
108
}
103
109
104
110
/// 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 > {
106
112
Err ( SoftBufferError :: Unimplemented )
107
113
}
108
114
}
109
115
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
+ }
115
121
116
122
// TODO: Move to NativeWindowBufferLockGuard?
117
123
unsafe impl < ' a , D , W > Send for BufferImpl < ' a , D , W > { }
118
124
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 > {
120
126
#[ 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
129
129
}
130
130
131
131
#[ 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
140
134
}
141
135
142
- pub fn age ( & self ) -> u8 {
136
+ #[ inline]
137
+ fn age ( & self ) -> u8 {
143
138
0
144
139
}
145
140
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
+ }
148
163
Ok ( ( ) )
149
164
}
150
165
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 ( )
153
171
}
154
172
}
0 commit comments