@@ -13,19 +13,14 @@ use crate::error::InitError;
13
13
use crate :: { Rect , SoftBufferError } ;
14
14
15
15
/// The handle to a window for software buffering.
16
- pub struct AndroidImpl < D : ? Sized , W : ? Sized > {
16
+ pub struct AndroidImpl < D , W > {
17
17
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
18
window : W ,
19
+ _display : PhantomData < D > ,
26
20
}
27
21
28
22
// TODO: Current system doesn't require a trait to be implemented here, even though it exists.
23
+ // impl SurfaceInterface<D, W> for ...
29
24
impl < D : HasDisplayHandle , W : HasWindowHandle > AndroidImpl < D , W > {
30
25
/// Create a new [`AndroidImpl`] from an [`AndroidNdkWindowHandle`].
31
26
///
@@ -45,9 +40,6 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> AndroidImpl<D, W> {
45
40
46
41
Ok ( Self {
47
42
native_window,
48
- // _display: DisplayHandle::borrow_raw(raw_window_handle::RawDisplayHandle::Android(
49
- // AndroidDisplayHandle,
50
- // )),
51
43
_display : PhantomData ,
52
44
window,
53
45
} )
@@ -73,7 +65,7 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> AndroidImpl<D, W> {
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 (
@@ -84,21 +76,30 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> AndroidImpl<D, W> {
84
76
}
85
77
86
78
pub fn buffer_mut ( & mut self ) -> Result < BufferImpl < ' _ , D , W > , SoftBufferError > {
87
- let lock_guard = self . native_window . lock ( None ) . map_err ( |err| {
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( )
86
+ assert ! (
87
+ matches!(
88
+ native_window_buffer. format( ) ,
89
+ // These are the only formats we support
90
+ HardwareBufferFormat :: R8G8B8A8_UNORM | HardwareBufferFormat :: R8G8B8X8_UNORM
91
+ ) ,
92
+ "Unexpected buffer format {:?}, please call .resize() first to change it to RGBx8888" ,
93
+ native_window_buffer. format( )
99
94
) ;
100
95
101
- Ok ( BufferImpl ( lock_guard, PhantomData , PhantomData ) )
96
+ let buffer = vec ! [ 0 ; native_window_buffer. width( ) * native_window_buffer. height( ) ] ;
97
+
98
+ Ok ( BufferImpl {
99
+ native_window_buffer,
100
+ buffer,
101
+ marker : PhantomData ,
102
+ } )
102
103
}
103
104
104
105
/// Fetch the buffer from the window.
@@ -107,48 +108,58 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> AndroidImpl<D, W> {
107
108
}
108
109
}
109
110
110
- pub struct BufferImpl < ' a , D : ?Sized , W > (
111
- NativeWindowBufferLockGuard < ' a > ,
112
- PhantomData < & ' a D > ,
113
- PhantomData < & ' a W > ,
114
- ) ;
111
+ pub struct BufferImpl < ' a , D : ?Sized , W > {
112
+ native_window_buffer : NativeWindowBufferLockGuard < ' a > ,
113
+ buffer : Vec < u32 > ,
114
+ marker : PhantomData < ( & ' a D , & ' a W ) > ,
115
+ }
115
116
116
117
// TODO: Move to NativeWindowBufferLockGuard?
117
118
unsafe impl < ' a , D , W > Send for BufferImpl < ' a , D , W > { }
118
119
119
120
impl < ' a , D : HasDisplayHandle + ?Sized , W : HasWindowHandle > BufferImpl < ' a , D , W > {
120
121
#[ inline]
121
122
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
- // }
123
+ & self . buffer
129
124
}
130
125
131
126
#[ inline]
132
127
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
- }
128
+ & mut self . buffer
140
129
}
141
130
142
131
pub fn age ( & self ) -> u8 {
143
132
0
144
133
}
145
134
146
- pub fn present ( self ) -> Result < ( ) , SoftBufferError > {
147
- // Dropping the guard automatically unlocks and posts it
135
+ // TODO: This function is pretty slow this way
136
+ pub fn present ( mut self ) -> Result < ( ) , SoftBufferError > {
137
+ let input_lines = self . buffer . chunks ( self . native_window_buffer . width ( ) ) ;
138
+ for ( output, input) in self
139
+ . native_window_buffer
140
+ . lines ( )
141
+ . expect ( "Nonplanar format" )
142
+ . zip ( input_lines)
143
+ {
144
+ // .lines() removed the stride
145
+ assert_eq ! ( output. len( ) , input. len( ) * 4 ) ;
146
+
147
+ for ( i, pixel) in input. iter ( ) . enumerate ( ) {
148
+ // Swizzle colors from RGBX to BGR
149
+ let [ b, g, r, _] = pixel. to_le_bytes ( ) ;
150
+ output[ i * 4 ] . write ( b) ;
151
+ output[ i * 4 + 1 ] . write ( g) ;
152
+ output[ i * 4 + 2 ] . write ( r) ;
153
+ // TODO alpha?
154
+ }
155
+ }
148
156
Ok ( ( ) )
149
157
}
150
158
151
159
pub fn present_with_damage ( self , _damage : & [ Rect ] ) -> Result < ( ) , SoftBufferError > {
152
- Err ( SoftBufferError :: Unimplemented )
160
+ // TODO: Android requires the damage rect _at lock time_
161
+ // Since we're faking the backing buffer _anyway_, we could even fake the surface lock
162
+ // and lock it here (if it doesn't influence timings).
163
+ self . present ( )
153
164
}
154
165
}
0 commit comments