Skip to content

Commit 81eff2e

Browse files
committed
android: Make the backend zero-copy
1 parent afa87bb commit 81eff2e

1 file changed

Lines changed: 19 additions & 21 deletions

File tree

src/backends/android.rs

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use raw_window_handle::AndroidNdkWindowHandle;
1212
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawWindowHandle};
1313

1414
use crate::error::InitError;
15-
use crate::{util, BufferInterface, Pixel, Rect, SoftBufferError, SurfaceInterface};
15+
use crate::{BufferInterface, Pixel, Rect, SoftBufferError, SurfaceInterface};
1616

1717
/// The handle to a window for software buffering.
1818
#[derive(Debug)]
@@ -52,7 +52,7 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Android
5252
&self.window
5353
}
5454

55-
/// Also changes the pixel format to [`HardwareBufferFormat::R8G8B8A8_UNORM`].
55+
/// Also changes the pixel format to [`HardwareBufferFormat::R8G8B8X8_UNORM`].
5656
fn resize(&mut self, width: NonZeroU32, height: NonZeroU32) -> Result<(), SoftBufferError> {
5757
let (width, height) = (|| {
5858
let width = NonZeroI32::try_from(width).ok()?;
@@ -99,12 +99,8 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Android
9999
));
100100
}
101101

102-
let buffer =
103-
vec![Pixel::default(); native_window_buffer.stride() * native_window_buffer.height()];
104-
105102
Ok(BufferImpl {
106103
native_window_buffer,
107-
buffer: util::PixelBuffer(buffer),
108104
})
109105
}
110106

@@ -117,7 +113,6 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Android
117113
#[derive(Debug)]
118114
pub struct BufferImpl<'surface> {
119115
native_window_buffer: NativeWindowBufferLockGuard<'surface>,
120-
buffer: util::PixelBuffer,
121116
}
122117

123118
// TODO: Move to NativeWindowBufferLockGuard?
@@ -138,7 +133,20 @@ impl BufferInterface for BufferImpl<'_> {
138133

139134
#[inline]
140135
fn pixels_mut(&mut self) -> &mut [Pixel] {
141-
&mut self.buffer
136+
let native_buffer = self.native_window_buffer.bytes().unwrap();
137+
// assert_eq!(
138+
// native_buffer.len(),
139+
// self.native_window_buffer.stride() * self.native_window_buffer.height()
140+
// );
141+
// TODO: Validate that Android actually initializes (possibly with garbage) the buffer, or
142+
// let softbuffer initialize it, or return MaybeUninit<Pixel>?
143+
// i.e. consider age().
144+
unsafe {
145+
std::slice::from_raw_parts_mut(
146+
native_buffer.as_mut_ptr().cast(),
147+
native_buffer.len() / 4,
148+
)
149+
}
142150
}
143151

144152
#[inline]
@@ -147,7 +155,7 @@ impl BufferInterface for BufferImpl<'_> {
147155
}
148156

149157
// TODO: This function is pretty slow this way
150-
fn present_with_damage(mut self, damage: &[Rect]) -> Result<(), SoftBufferError> {
158+
fn present_with_damage(self, damage: &[Rect]) -> Result<(), SoftBufferError> {
151159
// TODO: Android requires the damage rect _at lock time_
152160
// Since we're faking the backing buffer _anyway_, we could even fake the surface lock
153161
// and lock it here (if it doesn't influence timings).
@@ -158,18 +166,8 @@ impl BufferInterface for BufferImpl<'_> {
158166
// when the enlarged damage region is not re-rendered?
159167
let _ = damage;
160168

161-
// Unreachable as we checked before that this is a valid, mappable format
162-
let native_buffer = self.native_window_buffer.bytes().unwrap();
163-
164-
// Write RGB(A) to the output.
165-
// TODO: Use `slice::write_copy_of_slice` once stable and in MSRV.
166-
// TODO(madsmtm): Verify that this compiles down to an efficient copy.
167-
for (pixel, output) in self.buffer.iter().zip(native_buffer.chunks_mut(4)) {
168-
output[0].write(pixel.r);
169-
output[1].write(pixel.g);
170-
output[2].write(pixel.b);
171-
output[3].write(pixel.a);
172-
}
169+
// The surface will be presented when it is unlocked, which happens when the owned guard
170+
// is dropped.
173171

174172
Ok(())
175173
}

0 commit comments

Comments
 (0)