Skip to content

Commit 3026298

Browse files
committed
Add methods to get locked buffer from Surface.
Bug: 307535208 Test: atest libnativewindow_rs-internal_test Change-Id: Ib9a824a72d1d415dddd82e477d55200765d0b9e6
1 parent 78c6534 commit 3026298

3 files changed

Lines changed: 91 additions & 6 deletions

File tree

libs/nativewindow/rust/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@ extern crate nativewindow_bindgen as ffi;
1919
mod handle;
2020
mod surface;
2121

22-
pub use handle::NativeHandle;
23-
pub use surface::Surface;
24-
2522
pub use ffi::{AHardwareBuffer_Format, AHardwareBuffer_UsageFlags};
23+
pub use handle::NativeHandle;
24+
pub use surface::{buffer::Buffer, Surface};
2625

2726
use binder::{
2827
binder_impl::{BorrowedParcel, UnstructuredParcelable},

libs/nativewindow/rust/src/surface.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,27 @@
1414

1515
//! Rust wrapper for `ANativeWindow` and related types.
1616
17+
pub(crate) mod buffer;
18+
1719
use binder::{
1820
binder_impl::{BorrowedParcel, UnstructuredParcelable},
1921
impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable,
2022
unstable_api::{status_result, AsNative},
2123
StatusCode,
2224
};
2325
use bitflags::bitflags;
26+
use buffer::Buffer;
2427
use nativewindow_bindgen::{
2528
ADataSpace, AHardwareBuffer_Format, ANativeWindow, ANativeWindow_acquire,
2629
ANativeWindow_getBuffersDataSpace, ANativeWindow_getBuffersDefaultDataSpace,
27-
ANativeWindow_getFormat, ANativeWindow_getHeight, ANativeWindow_getWidth,
30+
ANativeWindow_getFormat, ANativeWindow_getHeight, ANativeWindow_getWidth, ANativeWindow_lock,
2831
ANativeWindow_readFromParcel, ANativeWindow_release, ANativeWindow_setBuffersDataSpace,
2932
ANativeWindow_setBuffersGeometry, ANativeWindow_setBuffersTransform,
30-
ANativeWindow_writeToParcel,
33+
ANativeWindow_unlockAndPost, ANativeWindow_writeToParcel, ARect,
3134
};
3235
use std::error::Error;
3336
use std::fmt::{self, Debug, Display, Formatter};
34-
use std::ptr::{null_mut, NonNull};
37+
use std::ptr::{self, null_mut, NonNull};
3538

3639
/// Wrapper around an opaque C `ANativeWindow`.
3740
#[derive(PartialEq, Eq)]
@@ -153,6 +156,43 @@ impl Surface {
153156
Ok(ADataSpace(data_space))
154157
}
155158
}
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+
}
156196
}
157197

158198
impl Drop for Surface {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright (C) 2024 The Android Open Source Project
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
use super::{ErrorCode, Surface};
16+
use nativewindow_bindgen::ANativeWindow_Buffer;
17+
use std::ptr::null_mut;
18+
19+
/// An empty `ANativeWindow_Buffer`.
20+
pub const EMPTY: ANativeWindow_Buffer = ANativeWindow_Buffer {
21+
width: 0,
22+
height: 0,
23+
stride: 0,
24+
format: 0,
25+
bits: null_mut(),
26+
reserved: [0; 6],
27+
};
28+
29+
/// Rust wrapper for `ANativeWindow_Buffer`, representing a locked buffer from a [`Surface`].
30+
pub struct Buffer<'a> {
31+
/// The wrapped `ANativeWindow_Buffer`.
32+
pub buffer: ANativeWindow_Buffer,
33+
surface: &'a mut Surface,
34+
}
35+
36+
impl<'a> Buffer<'a> {
37+
pub(crate) fn new(buffer: ANativeWindow_Buffer, surface: &'a mut Surface) -> Self {
38+
Self { buffer, surface }
39+
}
40+
41+
/// Unlocks the window's drawing surface which was previously locked to create this buffer,
42+
/// posting the buffer to the display.
43+
pub fn unlock_and_post(self) -> Result<(), ErrorCode> {
44+
self.surface.unlock_and_post()
45+
}
46+
}

0 commit comments

Comments
 (0)