|
14 | 14 |
|
15 | 15 | //! Rust wrapper for `ANativeWindow` and related types. |
16 | 16 |
|
| 17 | +pub(crate) mod buffer; |
| 18 | + |
17 | 19 | use binder::{ |
18 | 20 | binder_impl::{BorrowedParcel, UnstructuredParcelable}, |
19 | 21 | impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable, |
20 | 22 | unstable_api::{status_result, AsNative}, |
21 | 23 | StatusCode, |
22 | 24 | }; |
23 | 25 | use bitflags::bitflags; |
| 26 | +use buffer::Buffer; |
24 | 27 | use nativewindow_bindgen::{ |
25 | 28 | ADataSpace, AHardwareBuffer_Format, ANativeWindow, ANativeWindow_acquire, |
26 | 29 | ANativeWindow_getBuffersDataSpace, ANativeWindow_getBuffersDefaultDataSpace, |
27 | | - ANativeWindow_getFormat, ANativeWindow_getHeight, ANativeWindow_getWidth, |
| 30 | + ANativeWindow_getFormat, ANativeWindow_getHeight, ANativeWindow_getWidth, ANativeWindow_lock, |
28 | 31 | ANativeWindow_readFromParcel, ANativeWindow_release, ANativeWindow_setBuffersDataSpace, |
29 | 32 | ANativeWindow_setBuffersGeometry, ANativeWindow_setBuffersTransform, |
30 | | - ANativeWindow_writeToParcel, |
| 33 | + ANativeWindow_unlockAndPost, ANativeWindow_writeToParcel, ARect, |
31 | 34 | }; |
32 | 35 | use std::error::Error; |
33 | 36 | use std::fmt::{self, Debug, Display, Formatter}; |
34 | | -use std::ptr::{null_mut, NonNull}; |
| 37 | +use std::ptr::{self, null_mut, NonNull}; |
35 | 38 |
|
36 | 39 | /// Wrapper around an opaque C `ANativeWindow`. |
37 | 40 | #[derive(PartialEq, Eq)] |
@@ -153,6 +156,43 @@ impl Surface { |
153 | 156 | Ok(ADataSpace(data_space)) |
154 | 157 | } |
155 | 158 | } |
| 159 | + |
| 160 | + /// Locks the window's next drawing surface for writing, and returns it. |
| 161 | + pub fn lock(&mut self, bounds: Option<&mut ARect>) -> Result<Buffer, ErrorCode> { |
| 162 | + let mut buffer = buffer::EMPTY; |
| 163 | + // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because |
| 164 | + // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` |
| 165 | + // and we have not yet released it. The other pointers must be valid because the come from |
| 166 | + // references, and aren't retained after the function returns. |
| 167 | + let status = unsafe { |
| 168 | + ANativeWindow_lock( |
| 169 | + self.0.as_ptr(), |
| 170 | + &mut buffer, |
| 171 | + bounds.map(ptr::from_mut).unwrap_or(null_mut()), |
| 172 | + ) |
| 173 | + }; |
| 174 | + if status != 0 { |
| 175 | + return Err(ErrorCode(status)); |
| 176 | + } |
| 177 | + |
| 178 | + Ok(Buffer::new(buffer, self)) |
| 179 | + } |
| 180 | + |
| 181 | + /// Unlocks the window's drawing surface which was previously locked, posting the new buffer to |
| 182 | + /// the display. |
| 183 | + /// |
| 184 | + /// This shouldn't be called directly but via the [`Buffer`], hence is not public here. |
| 185 | + fn unlock_and_post(&mut self) -> Result<(), ErrorCode> { |
| 186 | + // SAFETY: The ANativeWindow pointer we pass is guaranteed to be non-null and valid because |
| 187 | + // it must have been allocated by `ANativeWindow_allocate` or `ANativeWindow_readFromParcel` |
| 188 | + // and we have not yet released it. |
| 189 | + let status = unsafe { ANativeWindow_unlockAndPost(self.0.as_ptr()) }; |
| 190 | + if status == 0 { |
| 191 | + Ok(()) |
| 192 | + } else { |
| 193 | + Err(ErrorCode(status)) |
| 194 | + } |
| 195 | + } |
156 | 196 | } |
157 | 197 |
|
158 | 198 | impl Drop for Surface { |
|
0 commit comments